Laptop to Production

Ways to release

Rolling, blue/green and canary — and when each fits.

Time
40 minutes
Level
Beginner

Part 1: The problem

QuickCart, deploy night

QuickCart’s releases work like this: stop the API servers, copy the new code on, start them again. For about two minutes, every order fails. The team deploys at 11pm, when it hurts least.

One Tuesday, the new version has a bug in the delivery fee. The moment it starts, every customer is charged the wrong fee. Rolling back means doing the whole stop-copy-start again: two more minutes of failures, then the old bug-free version.

Leo asks the obvious question: why does every customer have to get a new version at the same moment?

The fix is the same for QuickCart as for anyone: stop giving everyone a new version at the same moment.

Part 2: The idea

Deploying means replacing the running version with a new one while customers keep using it. There are a few standard ways to do the replacement. They all end in the same place, with everyone on the new version. They differ in how traffic moves from old to new, and that decides what happens when the new version is bad.

The four ways

StrategyHow traffic movesIf the new version is badExtra costUndoing it
RecreateStop everything, then start the new versionEveryone gets it, after a gap with no serviceNoneDo it all again
RollingReplace servers a few at a timeA growing share gets it until someone noticesNone, or one extra serverRoll back, a few servers at a time
Blue/greenBuild a full copy with the new version, then switch all traffic at onceEveryone gets it, but only until you switch backA second full copy, for a whileInstant: switch back
CanarySend a small share of traffic to the new version, then grow itOnly the small share gets it, and the release is stoppedSmall: one extra server, or noneInstant: send the share back

QuickCart’s current method is recreate. It’s the simplest, and the only one with downtime built in.

Key point: All four end with everyone on the new version. What differs is how traffic moves, which decides how many customers a bad version reaches before you stop it.

What each one needs

StrategyYou need
RollingA load balancer that stops sending traffic to a server before it’s replaced, and health checks so it only sends traffic to servers that work
Blue/greenA way to switch all traffic at once, usually a load balancer or DNS, and room for a second copy
CanaryA way to split traffic by percentage, and monitoring that compares the canary with the old version, and rules for when to stop

The canary’s rules are called abort criteria, and they’re written down before the release starts. For example: if the canary’s error rate is more than double the old version’s for five minutes, send all traffic back. The best pipelines apply them automatically. Canary from a pipeline builds exactly that.

Old and new run side by side

In rolling and canary releases, and briefly in blue/green, both versions answer requests at the same time, and both use the same database. So every database change has to work with both versions:

SafeBreaks the version that doesn’t expect it
Adding a new column or tableRenaming a column
Adding a column with a default valueRemoving a column
Removing a column, in a later release, once nothing uses itChanging a column’s type

This pattern is called expand, then contract: add the new thing, move the code over, and remove the old thing only when nothing uses it any more.

Choosing one

SituationA good fit
A small internal tool where a minute of downtime is fineRecreate
Most services, most of the timeRolling, with good health checks
A risky change you want to test fully before anyone sees it, with an instant way backBlue/green
A change to something customers depend on, like checkoutCanary

Part 3: See it

The three strategies release the same version side by side. Release a good version first. Then switch to Bad and release again. Watch how traffic moves, and how many customers the bad version reaches.

The new version is

Rolling

Replace servers a few at a time
Servers running: 4
v1v1v1v1
Traffic on version 2: 0%
Four servers, all on version 1.

Blue/green

Build a full copy, then switch
Servers running: 4
v1v1v1v1
Traffic on version 2: 0%
Blue: four servers on version 1, taking all traffic.

Canary

A small share first, then grow
Servers running: 4
v1v1v1v1
Traffic on version 2: 0%
Four servers on version 1.
ReadyAll three are running version 1. Choose Release it to release version 2 in three different ways at once.

What to notice: blue/green undid the bad version fastest, but it had already reached every customer. The canary reached only one in ten, because it was stopped while it was still small. Speed of undoing and number of customers hit are different things.

Part 4: Do it

Pennies — a few calls to a tiny Lambda function. Well under a cent, and inside the free allowance on most accounts.

You’ll run a real canary release on AWS, without any servers. You’ll put two versions of a small function behind one name, send 10% of calls to the new version, watch the split, then promote it, and finally switch back instantly. About 20 minutes.

The function runs on Lambda, which runs code without you managing a server. You don’t need to know Lambda yet: it’s just the simplest thing on AWS that can split traffic by percentage. The same ideas apply to servers and containers later in the course.

Check the region selector says N. Virginia (us-east-1), and that you’ve set up the AWS CLI in Set up your computer.

  1. Create the function

    In the AWS console: LambdaFunctionsCreate function

    FieldEnter
    Create functionAuthor from scratch
    Function namequickcart-menu
    RuntimeThe newest Node.js version in the list
    Architecturearm64
    PermissionsLeave the default: Create a new role with basic Lambda permissions

    Choose Create function.

    You should see

    The function’s page, with a Code tab showing a file called index.mjs.

  2. Write version 1 and publish it

    In the Code tab, replace everything in index.mjs with:

    index.mjs
    export const handler = async () => {
      return { version: "1", menu: "Margherita, Pepperoni" };
    };
    LineWhat it does
    export const handlerthe function Lambda calls. It must be called handler, because that’s what the default settings look for
    async () =>it takes no input we need, and may do slow work
    return { version: "1", menu: "Margherita, Pepperoni" }the answer, including which version sent it

    Choose Deploy. Then fix this code as a numbered version that can never change:

    In the AWS console: LambdaFunctionsquickcart-menuActionsPublish new version

    FieldEnter
    Version descriptionv1

    Choose Publish.

    You should see

    A message saying Version 1 was created. You’re now looking at version 1’s page.

  3. Point a name at version 1

    An alias is a fixed name that points at one or more versions. Callers always use the name; you change what it points at. That’s what makes the release strategies possible.

    In the AWS console: LambdaFunctionsquickcart-menuAliasesCreate alias

    FieldEnter
    Namelive
    Version1

    Leave Weighted alias empty. Choose Save.

    You should see

    The live alias, pointing at version 1.

  4. Write version 2 and publish it

    Go back to the function (Lambda → Functions → quickcart-menu), open the Code tab, and change index.mjs to:

    index.mjs
    export const handler = async () => {
      return { version: "2", menu: "Margherita, Pepperoni, Veggie" };
    };

    Choose Deploy, then Actions → Publish new version with the description v2, and Publish.

    You should see

    Version 2 created. Nobody is calling it yet: live still points at version 1. That’s deploy without release.

  5. Start the canary: 10% to version 2

    In the AWS console: LambdaFunctionsquickcart-menuAliasesliveEdit

    FieldEnter
    Version1
    Weighted alias: Additional version2
    Weight10

    Choose Save.

    You should see

    The alias shows version 1 at 90% and version 2 at 10%.

  6. Call the alias and watch the split

    Now call live the way a real caller would. The console’s Test button is built for trying one version; to see which version answers each call through the alias, the terminal is simpler, because it prints that for you.

    Terminal
    aws lambda invoke --function-name quickcart-menu:live response.json
    PartWhat it means
    aws lambda invokecall a Lambda function once and wait for the answer
    --function-name quickcart-menu:livethe function, and after the colon the alias to call through
    response.jsona file to save the function’s answer in. It’s created in the folder you’re in
    You should see
    {
        "StatusCode": 200,
        "ExecutedVersion": "1"
    }

    ExecutedVersion is the version that answered. Run the same command ten or twenty times: press ↑ then Return to repeat it.

    You should see

    Mostly "ExecutedVersion": "1", and now and then "2". Over many calls, about 1 in 10 is version 2. With so few calls, you might see none or several; that’s chance, not a fault.

  7. Promote it

    The canary looks healthy, so give version 2 everyone. Edit live again:

    In the AWS console: LambdaFunctionsquickcart-menuAliasesliveEdit

    FieldEnter
    Version2
    Weighted alias: Additional versionRemove it, so there is none

    Choose Save, and run the invoke command a few more times.

    You should see

    "ExecutedVersion": "2" every time. The release is complete.

  8. Switch back instantly

    Say version 2 turns out to be wrong. Edit live once more and set Version to 1. Choose Save, and invoke again.

    You should see

    "ExecutedVersion": "1" every time. Version 2 still exists, so switching forward again is just as quick. This is the blue/green idea: two complete versions, and one pointer that moves between them.

  9. Clean-up step: Clean up

    In the AWS console: LambdaFunctionsquickcart-menuActionsDelete function

    Type confirm if asked, and choose Delete. This removes every version and the alias.

    Lambda also created a log group for the function’s logs. Delete it too:

    In the AWS console: CloudWatchLog groups/aws/lambda/quickcart-menuActionsDelete log group(s)

    Finally, remove the answer file from your laptop:

    Terminal
    rm response.json
    PartWhat it means
    rmremove a file
    response.jsonthe file aws lambda invoke wrote

    The IAM role Lambda created, named like quickcart-menu-role- followed by random letters, costs nothing. You can delete it in IAM → Roles if you like to keep things tidy.

Part 5: Check yourself

A new version has a bug that only shows up with real customers' data. Which strategy lets it reach the fewest customers before it's stopped?

What does blue/green need that rolling doesn't?

During a rolling release, old and new versions answer requests at the same time. What does that mean for a database change?

A canary is showing an error rate ten times higher than the old version. What should happen?

In the App Store, you release an update to 1% of users on day one, then more each day. Which strategy is that?

Part 6: Cheat sheet

On one card
Strategy or ideaIn one line
RecreateStop everything, start the new version. Downtime built in
RollingReplace servers a few at a time. No extra cost; bad versions spread until noticed
Blue/greenFull second copy, then switch all at once. Instant undo; everyone hit if bad
CanarySmall share first, grow while watching. Fewest customers hit
Abort criteriaThe rule for stopping a canary, written before you start
Expand, then contractDatabase changes that work with old and new versions at once
Rolling backUndoes code, not what the bad version already did
Lambda aliasA name pointing at one version, or two with weights
aws lambda invoke --function-name NAME:ALIAS out.jsonCall through an alias; ExecutedVersion says who answered

Finished the build and the quiz? Mark it done to fill in its stop on the route map.