top of page

Staging vs. Production: Why “Works in Testing” Still Fails After Deployment

Lisa Perry
Oct 6
3 min read

Every team has lived this one. The build passed in staging. QA signed off. Someone hit deploy, and ten minutes later the support inbox lit up.

Nobody was careless. Staging just isn't production, and the gap between them is where most post-release failures hide. Closing it is the real job behind any list of software testing best practices for web applications.

Staging is a model, and model’s drift

A staging environment is an imitation of production. Imitations get stale. Somebody patches a production server at 2 a.m. and forgets staging. A feature flag gets flipped in one place only. Over a few months the two environments become cousins instead of twins.

The Twelve-Factor App methodology describes three gaps between development and production: time, people and tools. Its warning about tools is the one that bites most often. If you test against one database engine and run another in production, passing tests prove less than you think. Small incompatibilities between backing services are exactly how code that looked fine ends up failing live.

Where “works in testing” usually breaks

The same handful of culprits show up again and again.

Data. Staging holds a few thousand tidy records. Production holds years of messy ones: null values, strange characters, duplicate accounts, a customer whose name is 90 characters long. Queries that fly on small tables crawl on big ones.

Configuration. Environment variables, API keys, timeouts, SSL certificates and feature flags differ between environments by design. Any of them can be wrong in one place.

Traffic. Staging sees a few testers. Production sees concurrency, retries, bots and the occasional traffic spike you didn't plan for.

Third parties. Payment gateways and email providers often run-in sandbox mode during testing. Live behavior, including rate limits, can differ.

Security settings. Debug pages left on; default accounts left active. OWASP's guidance on security misconfiguration says development, QA and production environments should all be configured identically, with different credentials used in each. Identical settings, separate secrets.

Fixes that actually help

Teams that get fewer nasty surprises tend to follow the same software testing best practices for production-ready software.

  1. Keep environments close. Same operating system, same database engine and version, same container images, same infrastructure code. Build both from one source of truth so drift can't creep in quietly.

  2. Test with realistic data. Use anonymized copies of production data or a generator that produces ugly, varied records. Strip anything personal first.

  3. Verify configuration automatically. Google's SRE book describes configuration tests that look at production to see how a binary is actually configured and report discrepancies against what's in version control. Run a check like that after every deploy.

  4. Load-test before launch. Simulate expected traffic, then double it. Watch for slow queries, exhausted connections and memory that climbs and never comes back down.

  5. Release in small steps. Canary releases and staged rollouts put a new version in front of a sliver of users first. If something breaks, few people notice.

  6. Make rollback boring. Practice it until it's routine.

  7. Monitor from the first minute. Compare error rates before and after every deploy.

Fitting this into your process

None of this replaces what you already do. Unit and integration tests catch logic errors early, and they remain among the most important software testing best practices in software development. Staging then catches deployment errors, and production monitoring catches the rest.

A sound software testing process for web applications has layers, and each layer answers a different question. Does the code work? Do the pieces work together? Does the deployed system behave under realistic conditions?

Teams building services that must stay up should favor software testing techniques for reliable software development that include fault injection and failure rehearsals. Pull a dependency out on purpose and see whether the app degrades gracefully.

Pick the software testing methods for high-quality software that match your risk. A checkout flow deserves more scrutiny than a marketing page. A good set of software testing strategies for production software puts the heaviest checks where failure costs the most money or trust.

These habits matter even more now, because software testing best practices for modern applications have to cover distributed services, third-party APIs and frequent releases. More moving parts means more places for environments to disagree.

The takeaway

“It worked on staging” isn't proof. It's a data point. Treat staging as a rehearsal, treat production as the real performance, and build in the safety nets you'd want if the curtain went up with no warning.

Google's engineers put it bluntly in the SRE book: if you haven't tried it, assume it's broken. Good advice for any deploy day.

Comments


bottom of page