Guide

An environment is a complete place to run your software, such as a laptop, a test stack or production. Every long-lived environment costs money, drifts from the others and needs its own migrations. The question is how few you can get away with, and how closely the ones you keep match production.

The ladder

A workable ladder for a small product team looks like this.

EnvironmentPurposeLifetime
LocalDevelopment loop and unit testsDeveloper machine
Preview (ephemeral)One stack per pull requestHours to days; destroyed on merge
StagingProduction-like integration, migration rehearsal, QALong-lived
ProductionPaying usersLong-lived

Some teams add a shared dev environment between local and staging, or a disaster-recovery standby of production. Each long-lived environment multiplies the cost and the migration work.

Trade-off

More environments catch integration bugs earlier and give QA a stable place to work. Fewer environments cut spend and force parity, because you cannot paper over a bug in a fifth snowflake. Add another long-lived environment only when a concrete workflow demands it, such as a regulated approval step or a partner sandbox.

Parity means the same shape

Parity does not mean identical instance sizes. It means the same shape. Staging can be smaller and single-zone. It should use the same major database engine version, the same authentication mode, the same queue semantics and the same feature-flag evaluation path.

Fine:       staging is 1 zone, 2 small nodes, Postgres 16
Not fine:   staging runs SQLite while production runs Postgres 16
Not fine:   staging skips TLS while production requires it

Ephemeral previews

Ephemeral environments are built from infrastructure as code and your CI pipeline. Open a pull request and get a URL. The app runs against a throwaway database, where you can exercise migrations. On merge, the stack is torn down. That replaces "please don't break the shared dev database".

Common mistakes

  • Keeping many long-lived environments. Each one drifts and needs care.
  • Making staging a different shape. It then passes bugs that production will fail.
  • Sharing a dev database across pull requests. One PR's changes break another's tests.

Check yourself

  1. What is the difference between parity and identical sizing? Answer: Parity is about the same shape, such as engine, auth and queue behaviour. Size can differ.
  2. Why are ephemeral previews better than one shared dev database? Answer: Each preview is isolated, so one change cannot corrupt another's data.

Key takeaways

  • Keep a small ladder: local, ephemeral previews, one staging, production.
  • Parity means the same shape. Size can be smaller.
  • Ephemeral environments built from code replace shared dev databases.

Further learning

Next, see how the settings themselves are layered and validated when the app starts: config layering and validation.