Dev, staging and production: what each environment is and how to separate them on AWS

What question each environment answers, how they really differ and how to separate them on AWS with distinct accounts, with a runnable rule to avoid touching production by mistake.

In this article
In 30 seconds

Three environments are not three names: each answers a different question and is best separated into its own AWS account, because the account is the isolation boundary for identity and access.

1. What each environment is#

An environment is a copy of your application with its own configuration, data and access. Almost every team uses three: development (dev), staging and production. The names matter less than the question each one answers.

EnvironmentQuestion it answersDataWho has accessHow it is deployed
DevelopmentDoes my change work?Synthetic or testWhoever developsFrom your machine or automatic on every branch
StagingDoes it work like production?Reduced and anonymized copyThe team and QAWith the same process as production, after each merge
ProductionDo customers use it?RealUsers; minimal human accessWith approval and a rollback plan

Development is where you try your change; staging is the dress rehearsal with a configuration as close as possible to production; production is what customers use. If two environments answer the same question, one is redundant.

2. How they really differ#

Beyond the name, four things set one environment apart from another.

  • Data: dev uses synthetic data; staging, a reduced and anonymized copy; production, real data. Never copy real personal data into staging without anonymizing it.
  • Access: the more real users, the less human access. In production you go in through the deployment process, not the console.
  • Size and cost: staging is usually a smaller version of production with the same infrastructure code and different variables.
  • Alerts: a failure in dev wakes nobody; one in production does. Configure alerts per environment.

The useful rule is that staging should fail for the same reasons as production: if its configuration differs, what you see there does not predict what will happen.

3. How to separate them on AWS#

According to AWS's official guide on organizing with multiple accounts, an AWS account acts as an isolation boundary for identity and access management, and by default there is no access between accounts: if you use separate accounts for production and non-production, they stay isolated unless you enable communication. AWS charges for resource usage, not for the number of accounts, so separating adds no fee.

OptionIsolationWhen it makes sense
One AWS account per environmentThe strongest: no access between accounts unless you allow itProduction with real data or compliance requirements
Separate VPCs in one accountNetwork isolation, but shared permissions and limitsSmall teams starting out; move to accounts as risk grows
Only tags and namesNone really: a permissions mistake reaches everythingOnly for disposable tests; avoid with real data

That makes one account per environment the strongest option. The table compares the usual alternatives. If you already have a single account, Codifly's guide on separating environments on AWS explains the move to accounts with organizational units.

Go deeperSeparating environments (dev, staging, production) on AWS

Documentation: AWS: organizing your environment using multiple accounts ↗ · AWS Organizations: introduction ↗ · AWS: Well-Architected Framework ↗

4. A rule to avoid touching production by mistake#

The costliest mistakes happen when you run the right command in the wrong environment. A small check before each action prevents it: verify that the current account is the environment's and require confirmation for destructive actions in production.

python
ACCOUNTS = {"dev": "111111111111", "staging": "222222222222", "production": "333333333333"}  # example IDs

def validate(environment: str, current_account: str, destructive: bool, confirmed: bool) -> str:
    expected = ACCOUNTS.get(environment)
    if expected is None:
        return f"BLOCKED: unknown environment ({environment})"
    if current_account != expected:
        return f"BLOCKED: account {current_account} is not the one for {environment}"
    if environment == "production" and destructive and not confirmed:
        return "BLOCKED: in production, destructive actions require confirmation"
    return "OK"

print("1:", validate("staging", "222222222222", True, False))
print("2:", validate("production", "222222222222", False, False))
print("3:", validate("production", "333333333333", True, False))
print("4:", validate("production", "333333333333", True, True))
Account IDs are examples. Prints: 1: OK; 2: BLOCKED: account 222222222222 is not the one for production; 3: BLOCKED: in production, destructive actions require confirmation; 4: OK.

Call a function like this from your deployment scripts and your pipeline. It does not replace IAM permissions, which are the real defense, but it catches the human error before it reaches the API.

5. How to promote changes between environments#

A change should travel from dev to staging to production without being rebuilt.

  • Build the artifact once and promote it: what you tested in staging is the same thing that reaches production.
  • Use the same infrastructure code in all environments and change only the variables.
  • Test database migrations in staging with a volume similar to the real one.
  • Require approval before production and have a rollback plan ready.
  • Store secrets per environment in a secrets manager, never in the repository.

Go deeperEnvironment variables and DATABASE_URL in production: a full guide

6. Checklist#

Before treating your environments as separate, check the following.

  • Each environment has its own account or, at minimum, its own VPC and its own roles.
  • Staging uses anonymized data and production is the only one with real data.
  • Deployment to production requires approval and leaves a record.
  • Alerts and budgets are configured per environment.
  • Nobody uses production credentials from their machine for daily work.

Go deeperWhat is the best organizational structure for your AWS account?

Sources and scope

Documentation checked on October 17, 2026. Examples and decision criteria are editorial proposals; adapt them to your application's contract and validate them in an authorized test environment.

Compare these options

Compare cloud options

Review pricing, limits, conditions and sources for each option.

Open comparison
Advice

Is your case different?

Tell us your context and the options you're weighing. We reply with criteria and sources, and never sign you up for anything.

Request advice