Skip to content

Commit 8b99bc3

Browse files
committed
List and Table updates to ephemeral-preview-environments-cost-control-cleanup article
1 parent 7c1159d commit 8b99bc3

2 files changed

Lines changed: 96 additions & 68 deletions

File tree

  • src/content/articles/ephemeral-preview-environments-cost-control-cleanup

‎src/content/articles/ephemeral-preview-environments-cost-control-cleanup/index.mdx‎

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import sharedVsDedicatedDiagram from "./diagrams/shared-vs-dedicated-resource-co
1515
*[TTL]: Time To Live
1616
*[RDS]: Relational Database Service
1717

18-
Preview environments for every PR sound like a developer experience win until someone notices the cloud bill. I've seen this pattern play out multiple times: a team enables preview deployments, developers love the fast feedback loops, and six weeks later finance is asking why infrastructure costs tripled.
18+
<Highlighter>Preview environments for every PR sound like a developer experience win until someone notices the cloud bill.</Highlighter> I've seen this pattern play out multiple times: a team enables preview deployments, developers love the fast feedback loops, and six weeks later finance is asking why infrastructure costs tripled.
1919

2020
The math is straightforward but easy to ignore. A 50-developer team with an average of 40 open PRs, each spawning a full stack with database, Redis, and object storage, is running 40 duplicate environments around the clock. Most sit idle — the PR author pushed code, tested for an hour, then moved on. But the database is still running. The load balancer is still running. The persistent volumes are still allocated.
2121

@@ -32,7 +32,12 @@ A good TTL policy has three layers. First, a hard maximum lifetime — environme
3232
The defaults should be aggressive. A 72-hour maximum lifetime and an 8-hour idle timeout cover the vast majority of legitimate use cases. PRs that need longer — demo environments, long-running feature branches — can request an extension via a label or approval workflow.
3333

3434
<Table
35-
variant="vertical-column-delineation-table"
35+
variant="grid-and-accent-header-table"
36+
fullWidth={false}
37+
classes={{
38+
figure: "mt-8 mb-8",
39+
tbody: '!text-content',
40+
}}
3641
content={{
3742
figure: "TTL policy tiers for different use cases.",
3843
thead: { th: ["Policy", "Max Lifetime", "Idle Timeout", "Use Case"] },
@@ -93,6 +98,7 @@ The most impactful cost optimization is using shared infrastructure with logical
9398

9499
<Diagram
95100
src={sharedVsDedicatedDiagram}
101+
magnifyButtonPosition="top-left"
96102
title="Shared vs dedicated resource cost comparison."
97103
description="Flowchart comparing dedicated preview databases with a shared database model. In the Dedicated (Expensive) group are three separate databases labeled PR-123 DB, PR-124 DB, and PR-125 DB. In the Shared (Cost-Effective) group, one Shared DB branches into three isolated schemas: schema_pr_123, schema_pr_124, and schema_pr_125. A third group labeled Cost Comparison (db.t3.small) shows that three dedicated databases cost 3 x $30/mo = $90/mo, while one shared database costs 1 x $30/mo = $30/mo. Dotted arrows connect the dedicated databases to the higher cost and the shared database to the lower cost. The diagram demonstrates that logical isolation within a shared service can preserve separation while dramatically lowering per-preview infrastructure cost."
98104
/>
@@ -116,23 +122,24 @@ Deleting an environment when its TTL expires works, but sometimes you want a mid
116122
Hibernation works well for environments that are idle but might be needed again. A developer working on a feature for two weeks doesn't want their environment destroyed every night — they want it to stop costing money overnight and wake up when they need it.
117123

118124
<Table
119-
variant="vertical-column-delineation-table"
125+
variant="criteria-highlight-table"
126+
fullWidth={false}
120127
content={{
121128
figure: "Hibernation triggers and their cost impact.",
122-
thead: { th: ["Trigger", "Use Case", "Typical Savings"] },
129+
thead: { th: ["Trigger", "Typical Savings", "Use Case"] },
123130
tbody: {
124131
tr: [
125132
{
126133
th: "Hibernation timeout (4h idle)",
127-
td: ["Pause before TTL deletion", "40-60%"],
134+
td: ["40-60%", "Pause before TTL deletion"],
128135
},
129136
{
130137
th: "Schedule (nights/weekends)",
131-
td: ["Known non-working hours", "50-70%"],
138+
td: ["50-70%", "Known non-working hours"],
132139
},
133140
{
134141
th: "Budget pressure",
135-
td: ["Team approaching limit", "Variable"],
142+
td: ["Variable", "Team approaching limit"],
136143
},
137144
],
138145
},
@@ -143,30 +150,33 @@ Note the difference from TTL idle timeout: hibernation kicks in earlier (4 hours
143150

144151
The best hibernation UX is transparent to developers. When someone visits a hibernated environment URL, the system automatically wakes it. Show a loading page while resources start up, then redirect to the now-running environment. KEDA (Kubernetes Event-Driven Autoscaling) provides the scaling primitives — it can scale deployments to zero based on custom metrics (like HTTP request rate), then scale back up when traffic arrives. Custom ingress annotations or a lightweight proxy can intercept the initial request and trigger the wake.
145152

146-
The tradeoff is cold start time. Waking a hibernated environment takes 30-60 seconds for Kubernetes deployments to scale up, longer if databases need to start. For environments with dedicated RDS instances, AWS allows you to stop the instance (saving compute costs) while retaining storage — starting it again takes a few minutes. The inverse also applies: the loading page should be informative about this tradeoff. Explain that the environment was hibernated to save costs, show the PR number, and indicate expected wake time. Auto-refresh every few seconds so developers don't have to manually reload.
147-
148153
<Callout type="success">
149154
Hibernation with wake-on-access gives you the best of both worlds: environments are always "available" from the developer's perspective, but only incur costs when actively used. A 4-hour idle timeout with scheduled nights/weekends hibernation can reduce preview environment costs by 60%+.
150155
</Callout>
151156

157+
The tradeoff is cold start time. Waking a hibernated environment takes 30-60 seconds for Kubernetes deployments to scale up, longer if databases need to start. For environments with dedicated RDS instances, AWS allows you to stop the instance (saving compute costs) while retaining storage — starting it again takes a few minutes. The inverse also applies: the loading page should be informative about this tradeoff. Explain that the environment was hibernated to save costs, show the PR number, and indicate expected wake time. Auto-refresh every few seconds so developers don't have to manually reload.
158+
152159
## Putting It Together
153160

154161
These three strategies address the biggest cost drivers without requiring complex tooling:
155162

156163
<List
157-
variant="check-icons-list"
164+
variant="chevron-list"
165+
classes={{
166+
wrapper: "sm:ml-6 sm:mr-12 mb-6",
167+
}}
158168
items={[
159169
{
160-
text: "**TTL enforcement** catches abandoned environments automatically.",
161-
lead: "Start here — it's the highest-impact change with the lowest implementation effort.",
170+
lead: "TTL enforcement catches abandoned environments automatically",
171+
text: "Start here — it's the highest-impact change with the lowest implementation effort.",
162172
},
163173
{
164-
text: "**Shared infrastructure** turns per-environment database costs into marginal schema costs.",
165-
lead: "The savings compound as your PR volume grows.",
174+
lead: "Shared infrastructure turns per-environment database costs into marginal schema costs",
175+
text: "The savings compound as your PR volume grows.",
166176
},
167177
{
168-
text: "**Hibernation** eliminates idle compute costs while preserving developer experience.",
169-
lead: "Wake-on-access makes the cost savings invisible to users.",
178+
lead: "Hibernation eliminates idle compute costs while preserving developer experience",
179+
text: "Wake-on-access makes the cost savings invisible to users.",
170180
},
171181
]}
172182
/>

0 commit comments

Comments
 (0)