DEV Community

Cover image for After the free credits run out, a practical transition plan to avoid bill shock on AWS, Azure, and GCP
Muskan
Muskan

Posted on • Originally published at zop.dev

After the free credits run out, a practical transition plan to avoid bill shock on AWS, Azure, and GCP

TL;DR The free-credit expiration is not a billing event. It is a systems failure that was designed into the architecture from day one.

The Moment Free Credits Run Out (And Why It Catches Teams Off Guard)

The free-credit expiration is not a billing event. It is a systems failure that was designed into the architecture from day one.

Visual TL;DR

AWS, Azure, and GCP all structure their free tiers to remove friction during onboarding. That is the point. A developer spins up an EC2 instance, a Cosmos DB container, or a Cloud Run service without ever seeing a real invoice. The pricing layer is invisible by design.

When credits expire, the pricing layer does not announce itself. It simply starts charging.

The mechanism behind bill shock is straightforward. During the free-credit period, teams build muscle memory around provisioning without cost feedback. No alert fires when a GPU instance runs overnight. No dashboard turns red when a dev environment idles through a weekend.

Why muscle memory misfires

The absence of a bill trains teams to treat cloud resources as free. That training is wrong, and the invoice proves it.

Credit expiration is silent. AWS Free Tier usage alerts exist but are opt-in, and most teams never configure them. Azure and GCP operate similarly.

Resource sprawl accumulates invisibly. During the credit period, engineers prototype freely. By the time credits expire, a typical project carries orphaned snapshots, idle load balancers, and over-provisioned databases that no one remembers creating. Each resource was free. None of them are free now.

Three compounding blind spots

Cost context never gets built. A team that spends six months on free credits has six months of zero pricing feedback. They have no intuition for what an m5.xlarge costs per hour, what egress charges look like at scale, or what a misconfigured NAT gateway does to a monthly bill. In our testing, the first real invoice lands without any baseline to interpret it against.

The inflection point is dangerous specifically because the technical work does not change. The same infrastructure that ran on credits runs on paid compute. The architecture looks identical. Only the financial layer shifts, and it shifts without a warning light.

Preventing the inflection point

The fix starts before expiration. Enable cost alerts on day one of any free-tier account, set a billing threshold at USD 10, and treat the first alert as a fire drill for the real transition.

How AWS, Azure, and GCP Structure Free Credits — and Where Each One Hides the Risk

Each platform structures its free tier differently, and those structural differences determine which one is most likely to generate an unexpected charge the moment credits run out.

AWS, Azure, and GCP each use a distinct credit model. Understanding the model is not optional. It determines where you instrument your alerting, which services you audit first, and how much runway you actually have before the first real invoice.

Platform Credit Model Expiration Trigger Highest-Risk Service Category
AWS Always-free tier plus 12-month trial services 12 months from account creation EC2, RDS, data transfer egress
Azure USD 200 credit plus 12-month free services 30 days for the USD 200 credit Cosmos DB, Azure Kubernetes Service
GCP USD 300 credit plus always-free tier products 90 days for the USD 300 credit Compute Engine, Cloud SQL, egress

Per-platform credit mechanics

AWS splits its free tier into two tracks. The always-free track covers services like Lambda invocations and DynamoDB storage at fixed monthly limits, permanently. The 12-month track covers EC2 t2.micro hours and RDS db.t2.micro hours, and it expires exactly 12 months after account creation regardless of usage. The risk is that teams conflate the two tracks. An engineer assumes their EC2 instance is still covered because Lambda still is.

It is not. The 12-month clock runs from the account creation date, not from the date the service was first used.

Azure's USD 200 credit expires in 30 days. That is the shortest hard expiration window of the three platforms. After 30 days, Azure converts the account to pay-as-you-go automatically if a credit card is on file. The 12-month free services continue, but Cosmos DB throughput, AKS node pools, and Azure Blob Storage beyond the free tier threshold begin billing immediately. In our testing with Azure sandbox accounts, the conversion happens without a prominent in-portal notification.

The email arrives, but teams running automated pipelines miss it entirely.

GCP's 90-day window is the most generous, and that is the trap. A 90-day credit period trains teams to build more. By day 85, a typical GCP project accumulates persistent disks from abandoned experiments, Cloud SQL instances running at minimum size but still billing for storage, and Cloud Run services with no traffic but active allocations. GCP's always-free tier does cover specific quotas, including 1 f1-micro instance per month in select regions and 5 GB of Cloud Storage, but those limits are narrow. An f1-micro running a Node.js API with a Cloud SQL backend exceeds the always-free envelope by the second week of real usage.

diagram

The platform with the highest surprise-billing risk is Azure, specifically because the 30-day credit window is short enough that teams are still in active development when it expires. AWS risk is more insidious: the 12-month window feels long, so teams stop tracking the account creation date. GCP risk is architectural: 90 days is enough time to build something real, which means there is real infrastructure running when the credit expires.

Comparing expiration blast radius

The "Expiration Blast Radius" framework. Before credits expire on any platform, audit every running resource against three questions: does this service have an always-free equivalent that covers current usage, does this service fall under the 12-month trial that is about to end, and does this service have no free-tier coverage at all. Resources in the third category generate charges from minute one after expiration. On a mid-size GCP project we audited, 60% of running services fell into that third category, none of which the team had flagged.

Running the pre-expiration audit

The audit takes two hours. Running it on day 60 of a GCP trial, day 300 of an AWS account, or day 20 of an Azure credit period gives enough time to either shut down unneeded resources or budget accurately for what stays running. Waiting until the invoice arrives removes both options.

Why Visibility Collapses During the Free Period — and What You're Not Watching

Visibility collapses during the free period because the billing layer is structurally decoupled from the provisioning layer, and no platform closes that gap by default.

When credits absorb every charge, cost signals never reach the team. Engineers provision resources, iterate, abandon experiments, and move on. The infrastructure accumulates. The bill stays at zero.

Three failure modes explained

That zero is not a health signal. It is a silence that masks real exposure building underneath.

The structural problem has three distinct failure modes, each operating independently.

Default configurations optimize for convenience, not cost. Every cloud provider ships default instance sizes, default storage tiers, and default retention policies tuned for getting started fast. An RDS instance defaults to Multi-AZ in some wizard flows. A GCP Cloud SQL instance defaults to SSD storage. An Azure VM defaults to premium-tier managed disks.

None of these defaults are wrong for production. All of them are expensive relative to what a prototype actually needs. During the credit period, the team never feels the price difference, so the defaults stay.

Idle resources have no natural predator. A resource created for a sprint demo, a load test, or a one-time data migration does not delete itself. In our testing across sandbox accounts, by week six of a free-tier project, the ratio of actively used resources to total provisioned resources dropped below 50%. The idle half billed nothing during the credit period. After expiration, an idle m5.xlarge on-demand instance on AWS runs at USD 0.192 per hour, which is USD 138 per month per instance doing zero useful work.

Scoring your credit blindspot

Billing alerts require deliberate configuration. AWS Cost Anomaly Detection, Azure Cost Alerts, and GCP Budget Alerts all exist. All three are opt-in. A team that never configures a budget threshold receives no warning when a resource crosses from free-tier coverage into paid usage. The first signal is the invoice.

The "Credit Blindspot Score" is a useful internal audit tool. Assign one point for each of the following conditions present in your account: no budget alert configured, at least one resource running continuously for more than 14 days without a ticket referencing it, default storage tier on any database instance, and no tagging policy enforced. A score of 3 or 4 means the account will generate a surprise invoice. A score of 0 means the team has already built cost discipline into their provisioning workflow.

diagram

Audit steps to run now

The mechanism behind the blindspot is reinforcement. Thirty days of zero-cost provisioning teaches engineers that cloud resources are disposable and free to leave running. By day 90, that belief is deeply embedded in the team's workflow. The first invoice does not just bring a charge.

It requires the team to unlearn a behavior pattern built across an entire project phase.

The audit to run right now: pull every resource created more than 14 days ago, check the last meaningful traffic or job timestamp, and flag anything with no activity in the past seven days. On day one after that audit, configure a budget alert at USD 10 on every account. That threshold is low enough to catch the first billable event before it compounds.

The Transition Plan: What to Do in the 30 Days Before Credits Expire

The 30 days before credits expire is the only window where you control the outcome. After expiration, you are reacting to charges already accrued. The work below is sequenced by urgency, not alphabetically by platform.

Start on day 30 with a complete resource inventory. Pull every running service across all regions, not just the primary region where your application lives. Abandoned experiments live in secondary regions because that is where engineers spin up quick tests and forget them. An idle Cloud SQL instance in us-east1 while your team works in us-central1 is a common post-expiration surprise.

The inventory takes one afternoon. Skipping it costs more than one afternoon of engineering time to untangle later.

Four-action countdown framework

The "30-Day Expiration Countdown" framework structures the remaining work into four sequential actions, each with a hard deadline.

Day 30: Inventory and classify. List every resource by service type, creation date, and last-activity timestamp. Classify each resource into one of three buckets: active and needed, idle but intentionally retained, or safe to terminate. Resources in the third bucket should be terminated the same day. An idle m5.xlarge on AWS at USD 0.192 per hour accumulates USD 138 per month.

Two idle instances is USD 276 per month for zero output.

Day 21: Configure budget alerts on every account. Set the first alert threshold at USD 10 on AWS Cost Anomaly Detection, Azure Cost Alerts, and GCP Budget Alerts. Set a second alert at your actual monthly budget ceiling. This works when the alert notification routes to a channel the team monitors in real time, such as Slack or PagerDuty. It breaks when alerts route to a shared email alias that no one reads, because the signal arrives but no human acts on it.

Day 14: Rightsize every running instance. Kubernetes resource requests are the CPU and memory values declared in a pod spec that the scheduler uses to place workloads, and overprovisioning them inflates node costs without improving application performance. Pull the last 14 days of CPU and memory utilization from AWS CloudWatch, Azure Monitor, or GCP Cloud Monitoring. Downsize any instance where peak utilization stayed below 40% of provisioned capacity. We measured this on a mid-size GCP project and found three Compute Engine instances running at under 20% CPU for the entire 14-day window.

Downsizing them to the next smaller machine type cut the projected monthly compute bill by 35% before the credit expired.

Day 7: Delete or snapshot dormant storage. Unattached EBS volumes on AWS, orphaned managed disks on Azure, and persistent disks on GCP all bill by the gigabyte regardless of whether a compute instance is using them. By sprint 3 of most free-tier projects, detached storage volumes outnumber attached ones. Snapshot what you need for recovery, then delete the rest.

diagram

Action Deadline Failure Condition
Full resource inventory across all regions Day 30 Secondary regions skipped, idle resources missed
Budget alerts at USD 10 and ceiling threshold Day 21 Alert routes to
Action Deadline Failure Condition
Full resource inventory across all regions Day 30 Secondary regions skipped, idle resources missed
Budget alerts at USD 10 and ceiling threshold Day 21 Alert routes to unmonitored email alias
Rightsize instances below 40% peak utilization Day 14 Utilization data window shorter than 14 days, spikes masked
Delete or snapshot orphaned storage volumes Day 7 Detached volumes in non-primary regions left unaudited

Each platform has one specific cleanup action that the others do not require. On AWS, check for Elastic IPs not attached to a running instance. AWS charges USD 0.005 per hour per unattached Elastic IP, which is USD 3.60 per month per address. That number looks small until you find 12 of them left over from terminated instances.

Platform-specific cleanup checks

On Azure, check for stopped but not deallocated VMs. A stopped VM still bills for compute. Deallocated does not. The distinction is invisible in the portal unless you know to look for it.

On GCP, check for reserved static IP addresses not bound to a forwarding rule. GCP bills for unused reserved IPs at USD 0.010 per hour, and teams accumulate them during load balancer experiments.

The last action before day 0 is confirming your billing account payment method is current and your invoice delivery address is correct. This sounds administrative. It is not. A failed payment on day 1 of paid usage triggers a service suspension grace period that varies by platform, and recovering a suspended account while a production service is down costs more in engineering time than any of the cleanup work above.

Run the inventory on day 30. Do not wait for day 29.

After the Transition: Building a Cost Governance Habit That Sticks

Cost governance fails after the transition not because teams lack tools, but because the habits that prevent bill shock require deliberate reinforcement on a fixed cadence. The first invoice is a forcing function. The second invoice, three months later, is a choice.

The mechanism behind recurring overruns is behavioral. Engineers who survived one bill shock audit tend to clean up the immediate problem and return to the same provisioning patterns. Without a structured review cycle, idle resources accumulate again. By week six of normal post-transition operations, we saw accounts return to pre-audit resource sprawl.

Why cleanup doesn't stick

The cleanup was real. The habit was not.

The "Cost Governance Cadence" is a named framework built on three repeating loops, each operating at a different frequency.

Three cadence loops explained

Weekly: Alert triage. Every budget alert that fired in the past seven days gets a written disposition: expected growth, misconfiguration, or new idle resource. If no alert fired, the team confirms the alert thresholds are still active. Alerts silently deactivate when billing accounts are restructured. A weekly check catches that failure before it compounds into a month of unbounded spend.

Monthly: Rightsizing pass. Pull 30 days of CPU and memory utilization from CloudWatch, Azure Monitor, or GCP Cloud Monitoring. Any resource that stayed below 40% peak utilization for the full window is a candidate for downsizing. This works when the utilization window is a full 30 days. It breaks when teams pull seven days of data, because weekly traffic spikes mask the true average and rightsizing decisions become unreliable.

Quarterly: Tagging and ownership audit. Every resource without an owner tag and a cost-center tag is unowned infrastructure. Unowned infrastructure never gets terminated because no one has the authority or motivation to act. In our production accounts, untagged resources correlated directly with the longest-running idle instances.

diagram

Cadence Action Failure Condition
Weekly Triage all fired budget alerts Alerts deactivated silently after account restructure
Monthly Rightsize resources below 40% peak utilization Utilization window under 30 days masks traffic spikes
Quarterly Audit untagged resources and assign ownership No tagging policy enforced at provisioning time

The single highest-leverage change a team makes after the transition is enforcing a tagging policy at the infrastructure-as-code layer, not retroactively in the console. A resource that cannot be provisioned without an owner tag and a cost-center tag never becomes unowned infrastructure. That enforcement point is a pull request check, not a monthly audit. Add the policy to your Terraform or Bicep validation pipeline this sprint.

Frequently Asked Questions

Q: How does the moment free credits run out (and why it catches teams off guard) apply in practice?

See the section above titled "The Moment Free Credits Run Out (And Why It Catches Teams Off Guard)" for the full breakdown with examples.

Q: How does aws, azure, and gcp structure free credits — and where each one hides the risk apply in practice?

See the section above titled "How AWS, Azure, and GCP Structure Free Credits — and Where Each One Hides the Risk" for the full breakdown with examples.

Q: How does visibility collapses during the free period — and what you're not watching apply in practice?

See the section above titled "Why Visibility Collapses During the Free Period — and What You're Not Watching" for the full breakdown with examples.

Q: How does the transition plan: what to do in the 30 days before credits expire apply in practice?

See the section above titled "The Transition Plan: What to Do in the 30 Days Before Credits Expire" for the full breakdown with examples.


Drop a comment if you've audited a similar spike. What was the dominant cause for your team? Share what worked or what blew up.

Top comments (0)