← Concepts

阅读中文版本

Environment Parity

Environment parity keeps dev, CI, and production alike — same images, same dependencies, same configuration mechanism — because every difference is a class of bug only production can find.

testing

Definition

Environment parity is the practice of minimizing deliberate divergence between environments: identical container images promoted through stages, external dependencies emulated or provisioned the same way, and configuration injected through one mechanism. Gaps between environments define the bug classes invisible until production — version skew, data shapes, resource limits, timing.

Context and scope

A twelve-factor principle. Applied via containerized builds, ephemeral CI environments, testcontainers, and configuration management shared across stages.

Common misconceptions

  • Differences are intentional and documented — intentional differences still bite; parity demands each one be small, justified, and compensated by a test
  • Parity means production copies of everything — it means production-shaped everything: same kinds of dependency, same config mechanism, scaled sizes
  • Staging exists to catch what dev cannot — staging catches integration issues; parity failures specifically surface only when divergence is large

Anti-patterns

  • Installing different dependency versions in dev via global packages and discovering version skew in production
  • Configuring dev by hand and production by scripts, so the script path is never exercised before release
  • Emulating external services in CI with simplified fakes that lack the failure modes production exhibits

Related concepts

Authoritative source

https://12factor.net/dev-prod-parity

What it is

A bug that requires a divergent environment to appear cannot be found in a matching one. Parity reduces the bug surface to what the code itself does, rather than what the environment does differently.

How it works

Build once, promote the artifact: the same image moves through dev, CI, and production with configuration injected per stage. Dependencies run as the same containers locally and deployed — compose locally, orchestrate in prod. Time, randomness, and locale become explicit configuration rather than ambient environment accidents.

When to enforce

When bugs repeatedly trace to works-on-my-machine and not-in-staging: audit the divergence list, shrink it, and add a test for every remaining difference. Data parity deserves attention — production-shaped anonymized data beats uniform synthetic rows.

Pitfalls

Full-size parity is expensive; shape parity is the goal — same services and versions, scaled resources. Backing services version skew is the classic gap: dev on Postgres 16, prod on 15, planner differences surface only under load. Document the divergence ledger, or drift creeps back silently.