Staging exists to catch problems before users do. It stops doing that the moment it diverges from production in ways nobody is tracking – a different database version, a missing queue, one instance instead of three.
Mirror the shape, not the scale
Staging does not need production capacity. It does need production topology: the same components, the same connections, the same configuration mechanism. Smaller instances are fine; a missing load balancer is not, because it hides an entire class of bug.
| Aspect | Match production? |
|---|---|
| Service topology and dependencies | Yes – this is the point. |
| Software and engine versions | Yes. |
| Deployment mechanism | Yes – deploy the same way. |
| Instance sizes and counts | No – smaller is fine, but keep at least two where HA matters. |
| Data volume | No – but keep realistic shape and distribution. |
| Real customer data | No – anonymise or synthesise. |
Build it from the same code
If staging is described by the same infrastructure-as-code with a different variable file, drift is structurally difficult. If it was built by hand once, drift is guaranteed. This single decision does more for staging fidelity than any process.
Data that behaves like real data
- Generate volumes large enough that missing indexes actually hurt.
- Preserve distribution: some accounts with thousands of records, most with few.
- Include the awkward cases – unicode, long strings, nulls, old formats.
- Anonymise thoroughly if derived from production; do not merely rename fields.
- Refresh on a schedule so it does not drift into irrelevance.
Separate accounts make this easier
Running staging in its own cloud account removes a whole category of accident – a misdirected script, a policy that was broader than intended – and makes the cost of staging plainly visible. It is one of the clearest cases for account isolation.
Summary
Same shape, same versions, same deployment path, smaller scale, realistic but not real data, and its own account. Anything less and staging is theatre.