The moment we realized our staging environment was broken
It was 3 PM on a Thursday, and our team was scrambling. A critical API change had just been merged to main, but the staging environment—our supposed safety net—was showing false positives. The integration tests passed, but the mobile app was completely broken in production.
That's when we knew: our shared staging environment was failing us.
The Problem: Shared Staging Is Broken by Design
Like many engineering teams, we operated with a single, shared staging environment. Every developer deployed their changes to the same place, leading to:
Deployment conflicts: "Who deployed that breaking change?"
Cascading failures: One broken PR would block the entire team
Test contamination: Data from one test would leak into another
Delayed feedback: You'd only discover issues after merging your PR and deploying to staging
The "works on my machine" syndrome, now at scale
The worst part? Our API contracts were changing constantly, but we only discovered breaking changes during integration testing—often too late.
The Solution: Ephemeral Environments per PR
We made a radical change: every PR gets its own isolated, short-lived environment.
Here's our architecture:
Our Implementation Stack
Infrastructure: Kubernetes (EKS) with namespace-per-PR
Orchestration: Custom GitHub Action workflow
Database: Isolated RDS instance per environment
Contract Testing: Pact flow + OpenAPI validation
Cleanup: AWS Lambda that runs every hour, destroying environments older than 2 hours
The Game Changer: Automated Contract Testing
The magic wasn't just in isolated environments—it was in what we did with them. Every time a PR deployed to its ephemeral environment, we ran:
Consumer-Driven Contract Testing (Pact)
Our mobile and web clients would verify their expectations against the actual deployed API. If a change broke what the client expected, the PR would fail.Provider Contract Validation
We'd automatically verify that the deployed API matched our OpenAPI specification. If you added a required field without updating the spec, you'd know immediately.Schema Diff Detection
We compared the new API schema against the production baseline. Any breaking changes (removing fields, changing types, adding required properties) would trigger a review.Integration Smoke Tests
Each environment ran a suite of end-to-end tests with real client applications connecting to the backend.
The Results: 12 Breaking Changes Caught
In our first month with ephemeral environments, we caught 12 breaking API contract changes that would have:
Crashed our mobile app
Broken third-party integrations
Caused data corruption in production
Required emergency rollbacks
One Real Example
A developer modified the User object to rename user_id to userId for consistency. The OpenAPI spec was updated, but the mobile app's contract test immediately caught the mismatch:
text
❌ Contract violation: Expected 'user_id' but found 'userId'
Breaking change detected in GET /api/v2/users/123
The PR was blocked, the issue was fixed in 30 minutes, and the mobile app never broke.
The Economics: Cost vs. Value
You might think: "Ephemeral environments sound expensive." Let's do the math:
Before:
1 shared staging environment running 24/7: $500/month
1 production outage per month: $10,000+ in lost revenue
Developer hours wasted debugging environment issues: 40+ hours/month
After:
Ephemeral environments run ~8 hours/day (active PRs): ~$300/month
0 production-breaking API changes in 3 months
Developer productivity increased by ~30%
Net result: We're saving money AND shipping faster.
Lessons Learned
Start Small, Scale Smart
We didn't spin up full environments for every PR immediately. We started with just the critical backend services.Make Cleanup Aggressive
2-hour TTL seemed short initially, but developers learned to work faster. For long-running PRs, they could request extensions.Invest in Observability
Each environment had its own logging and metrics. We could debug failures without affecting others.Education is Key
Developers needed to understand why userId vs user_id matters. We created "Breaking Change 101" docs.Contract Tests Are Only Half the Battle
We also needed:
Load testing (some issues only appear under load)
Security scanning
Database migration testing
The Future: Beyond API Contracts
Now that we have the infrastructure, we're expanding:
Database migrations: Test schema changes on a copy of production data
Feature flags: Test features in isolation before global rollout
Performance benchmarks: Detect performance regressions per PR
Security scanning: Run vulnerability scans on each environment
Should You Do This?
Yes, if:
You have breaking changes that go to production
Your staging environment is a bottleneck
You have multiple services with dependencies
You want to ship faster with more confidence
Not yet, if:
You're a pre-revenue startup with no customers
Your infrastructure is manual and fragile
You're still working toward basic CI/CD
Getting Started: A Practical Roadmap
Week 1-2: Automation Foundation
Set up infrastructure-as-code (Terraform/CDK)
Create scripts to spin up/down environments
Define environment variables and secrets management
Week 3-4: Core Services
Start with your most critical microservice
Deploy it to an ephemeral environment per PR
Run basic smoke tests
Week 5-6: Contract Testing
Implement Pact or OpenAPI validation
Create test suites that verify contracts
Set up CI/CD integration
Week 7-8: Scale and Optimize
Add more services to the stack
Fine-tune resource allocation
Implement cost monitoring
Week 9+: Iterate
Gather developer feedback
Add database support
Enhance observability
The Bottom Line
Ephemeral staging environments transformed how we build software. We've gone from "breaking changes are inevitable" to "breaking changes are caught in PRs."
The 12 breaking changes we caught weren't just bugs—they were 12 production incidents that never happened.
That's not just a win for engineering. It's a win for every user who depends on our software.
Have you implemented ephemeral environments? What challenges did you face? Let's discuss in the comments!
Resources to Get Started
Kubernetes Namespaces: Kubernetes.io docs
Pact Contract Testing: Pact.io
GitHub Actions for Preview Deployments: GitHub Docs
AWS EKS Ephemeral Environments: AWS Quick Start
About the Author: I'm a lead engineer at a growing SaaS company, passionate about developer productivity and reliable systems. You can find me on GitHub and Twitter.
Have questions about implementing this in your org? Reach out—I'm happy to share our battle scars!
Top comments (0)