The "It Works on My Machine" Problem
You've tested the feature locally. It works perfectly. You deploy to production and — something breaks. A missing environment variable, a different database version, a third-party API that behaves differently in production. Sound familiar?
A staging environment is a production-like environment where you test changes before real users see them. It's not glamorous, but it prevents the most embarrassing bugs.
What Staging Should Mirror From Production
- Same OS and runtime versions — if production runs Ruby 3.3, staging should too
- Same environment variables — use real (but test) API keys
- Same database engine and version — PostgreSQL 16, not SQLite
- Similar data volume — a staging DB with 10 rows won't catch N+1 query problems that appear with 10,000 rows
- Same web server — Nginx in front, same as production
The Cheap Setup: One Extra Server
For most startups, staging doesn't need to be powerful. An AWS t3.micro ($8-10/month) running the same Docker Compose setup as production is perfectly adequate.
Your CI/CD pipeline then becomes:
- Push to
mainbranch → deploy to staging automatically - Test on staging (manually or with automated tests)
- Push a git tag (e.g.,
v1.2.0) → deploy to production
Database: Don't Use Production Data
Never copy production data to staging without anonymizing it first. Use a script that generates realistic fake data (names, emails, phone numbers) or use a sanitized dump. GDPR compliance aside, it's just good practice.
The ROI Is Clear
One production incident costs more in developer time, customer trust, and potential revenue loss than a year of staging server costs. It's not an expense — it's insurance.
Need help setting up a staging environment for your project? Get in touch.