Skip to content
Quest 09Advanced16 min

Dev, Staging and Prod

One stack class, several environments. The Pokédex needs a throwaway dev copy that anyone can delete, and a production copy that must never lose a card. In CDK that difference is a few lines of code, not a second project.

What you'll learn

  • Make the stack a class with props, then instantiate it once per environment with different ids and settings.
  • Decide removal behaviour per environment: DESTROY + auto-delete for dev, RETAIN for prod.
  • terminationProtection makes CloudFormation refuse to delete a stack. Tags.of(app).add(…) tags every taggable resource beneath the app.

Section 01

One class, many stacks

A stack is just a class. Give it a prop such as stage and it can create the same resources with different settings. Each instance needs a different id, because the id is the CloudFormation stack name.

Stage-aware stack
interface PokedexProps extends cdk.StackProps {
  stage: "dev" | "prod";
}

export class PokedexStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: PokedexProps) {
    super(scope, id, props);
    const isProd = props.stage === "prod";
    new s3.Bucket(this, "CardsBucket", {
      versioned: true,
      removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: !isProd,
    });
  }
}

const app = new cdk.App();
new PokedexStack(app, "PokedexDev", { stage: "dev" });
new PokedexStack(app, "PokedexProd", {
  stage: "prod",
  terminationProtection: true,
  env: { region: "ap-south-1" },
});

Section 02

Protect production

Prod keeps its bucket, and the stack itself can't be deleted until someone turns termination protection off: two independent safeguards against the same mistake. Dev stays easy to throw away, so people actually delete it, which keeps cost down.

For real accounts, split environments across accounts, not just stacks: a mistake in dev can then never touch prod data. env takes account and region; the exercise uses only the Region so it stays account-neutral.

Section 03

Tags

Tags are how cost reports and policies find your resources. Because constructs form a tree, you tag a node and everything below it inherits the tag. Put the project tag on the app, and every bucket, table and function in every stack carries it.

Tag the whole app
cdk.Tags.of(app).add("Project", "Pokedex");

Practice

Your turn

The stack takes a stage prop, but it destroys the bucket in every stage — including production. Make production keep its data (retain, no auto-delete) and dev stay disposable (no termination protection). Then create PokedexDev and PokedexProd from the same class: production gets termination protection and the ap-south-1 Region, and the whole app is tagged Project=Pokedex.

stage chooses the removal policy and autoDeleteObjects; two stacks; prod has terminationProtection and env.region; Tags.of(app).
Tab inserts two spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the code.
Simulated — no AWS calls

The simulator runs the constructs this course teaches, plus simple loops and helper methods. Other CDK code may not be recognised.

Check

Check your understanding

Quick Quiz · one question, as many tries as you need.

What should the production stack do differently from dev, to protect the Pokédex data?

Choose one answer.