Session 05: Cloud & Deployment — Docker, CI/CD, and Release Planning
What you'll get out of this session
Part 1: Cloud Infrastructure — The foundation everything runs on
You've seen system architecture on paper — monoliths, microservices, queues, caches. The next step: how do you get code from a dev's machine onto a production server, and why does that process need tight control?
From physical servers to the cloud
Opening a store the old way: you had to buy land, build the warehouse, wire up power and plumbing, and only then start selling. If you wanted to expand, you built another warehouse — a process that took months. The cloud is like renting space in a shopping mall: you pay monthly rent for your unit, and when you want another storefront you just sign up for one — no building from scratch.
Before the cloud existed, infrastructure was a logistics problem: ordering a server took 4–8 weeks, then you racked it in a data center, configured the network, and only then started deploying the app. By the time you'd scaled up for a campaign, it was usually already too late.
The cloud changed this by abstracting away the hardware. AWS EC2, Google Compute Engine, Azure VMs — you pick the specs, hit a button, and a server is ready in 30 seconds. No buying, no racking, no managing hardware.
Types of cloud service a PM will hear about:
IaaS (Infrastructure as a Service): Rent servers, storage, and networking. The team manages the OS, runtime, and application themselves. Most flexible, but requires an ops team with the right expertise.
PaaS (Platform as a Service): The cloud handles the OS and runtime; the team just pushes code. Heroku, Render, and Railway are the classic examples. A good fit for startups that want to move fast without a dedicated DevOps team.
SaaS (Software as a Service): Use finished software over the internet. Slack, Notion, Jira — no installing or operating anything.
Serverless — Doesn't actually mean no servers
Serverless functions (AWS Lambda, Vercel Functions, Cloudflare Workers) work on one principle: you write a function, the cloud handles the rest. The function only runs when a request comes in, and if there are no requests, it costs nothing — like turning on a light only when you need the room, instead of leaving it on all day.
A good fit for: API endpoints with uneven traffic, webhook handlers, background jobs that run on a schedule.
A poor fit for: long-running continuous processes, or apps that need a persistent database connection (because serverless restarts from scratch on every new request).
Part 2: Containers and Docker — Environment consistency
The problem Docker solves
Say you write a recipe on your gas stove at home. When another chef tries to recreate it on an induction stove at a restaurant, the result comes out completely different — same ingredients, same recipe. The problem is the execution environment, not the recipe.
Software is the same. A Node.js app needs the right Node version, the right list of libraries, the right environment variables, and sometimes a handful of system libraries. On the dev's machine (a Mac), everything is installed the Mac way. On the production server (Linux), the install works differently and versions may differ.
Docker solves this by packaging everything into an image — a complete snapshot of the entire environment needed to run the app. That image runs identically on any machine with Docker.
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Read this Dockerfile like an instruction sheet: "Start from the slim (alpine) build of Node 20, create the /app directory, copy in and install dependencies, copy in the code, open port 3000, then run server.js."
A PM doesn't need to write Dockerfiles. But when a dev says "there's an issue with the Docker image," you understand: that's a problem with the app's runtime environment, not with the code logic.
Part 3: Environments and CI/CD
The three environments and the role of each
Picture a Broadway play. Actors rehearse at home (development), then do a dress rehearsal in the theater before opening night (staging), and only then perform in front of a real audience (production). Nobody skips the dress rehearsal just because a deadline is looming.
Development (local): Where a developer writes code and tests it on their own machine. The database is usually a local copy or a separate dev database with fake data. This environment is unstable and can be reset at any time — and that's completely normal.
Staging: The closest possible copy of production — same infrastructure, same configuration, same deploy pipeline — but with no real users. This is where QA tests, where PMs review before a release, and where smoke tests run after each deploy.
A good staging environment needs: data similar to production (possibly an anonymized copy), the same third-party integrations (but in test mode), and equivalent monitoring.
Production: The real system. Every bug here directly affects users and revenue.
Why skipping staging is a mistake: A bug caught on staging costs a few hours of dev time to fix. A bug caught on production costs a few hours of dev time plus customer support, an incident report, and lost trust. The cost is lopsided, every single time.
CI/CD Pipeline — Automation that reduces human error
Continuous Integration (CI): Every time a developer pushes code to a branch and opens a Pull Request, the CI server (GitHub Actions, GitLab CI, CircleCI) automatically:
- Runs unit tests and integration tests
- Checks code style (linting) — like automated spell-checking
- Builds the Docker image to confirm the build isn't broken
- Reports the results back to the Pull Request
If any step fails, the PR can't be merged. This is the mechanism that keeps broken code out of the main codebase — the dev isn't blocking you, the system is protecting everyone.
Continuous Delivery (CD): After code is merged into the main branch:
- The CD pipeline automatically builds the Docker image for production
- Deploys to staging
- Runs automated smoke tests
- Notifies the team via Slack or email
- Waits for approval → deploys to production
What a PM can do in the pipeline: Many teams add a "Product sign-off" step to the pipeline — the PM reviews directly on staging before approving a deploy to production. This is a golden opportunity to catch UX issues before users ever see them.
Part 4: Release Strategy and Rollback Planning
Deployment strategies by risk level
There are many ways to get code onto production, each with a different risk level. The choice depends on the nature of the change and the team's capabilities.
Big bang release: Deploy all changes at once to 100% of users. Highest risk. Suitable for small, low-risk changes, or when the team doesn't yet have the infrastructure for a canary.
Blue/green deployment: Maintain two production environments in parallel. Blue is the version currently running, Green is the new version. Once testing is complete, switch all traffic from Blue to Green in seconds. Rollback is just switching back. The downside: double the infrastructure cost during the transition window.
Canary release: Ramp up gradually — 1% of users first, then 5%, 25%, 50%, and finally 100%. At each step, watch error rate, latency, and business metrics. If anything looks off, cut traffic to 0% in seconds. A good fit for changes that touch core flows like payments, login, or checkout.
Feature flags: Release code to production but keep the feature hidden. Turn it on or off per group of users without a new deployment. A good fit for A/B testing, geographic rollout, or rollout by user segment (for example: enable it early for premium users).
Rollback — The questions you must ask before every release
A rollback plan isn't optional. Before every significant release, a PM should ask the following questions.
Does this release have a database migration? A migration is a change to the structure of the database — for example, adding a new column, renaming a table, or deleting old data.
If there's a migration, can it be rolled back? Not always. Once you've dropped a column and the data in it is gone, there's no way to get it back.
If something goes wrong on production, how long does a rollback take? And who has the authority to make the rollback call, and what's the notification process?
A release that ships with a database migration can't be rolled back instantly the way a normal deploy can. This is why many teams practice "expand and contract": phase 1 only adds, never removes — so both the old and new code can run side by side. Phase 2 (cleaning up what's no longer needed) happens only after phase 1 has fully stabilized.
Further reading
- Docker — Getting Started — Docker's official docs, explaining containers from the ground up with hands-on examples.
- Vercel Deployment Documentation — A guide to deploying and understanding the CI/CD pipeline in practice with Vercel.
- GitHub Actions Documentation — The most popular CI/CD pipeline today, with concrete examples for many kinds of projects.
- BlueGreenDeployment — Martin Fowler — A short, precise explanation of the blue/green deployment strategy.
- Feature Toggles (aka Feature Flags) — Martin Fowler — A comprehensive piece on feature flags: when to use them and the risks to watch for.
Homework
Deploy the app from Session 01 to a real production URL.
- Grab the Replit project from Session 01 — if you didn't do it, create a simple page from scratch.
- Hit Run on Replit → get the public URL. Send the URL to at least one other person in the group to confirm they can reach it.
- Change a line of text in the code → run it again → reload the URL → confirm the change is live in production. This is the simplest possible deploy cycle.
- Share with the group: the app URL, one thing you changed, and this question: If 100 people were using the app at the moment you deployed, what happened to them?
What matters
- 1The cloud isn't just 'a server on the internet' — it changes how a team scales, deploys, and manages cost. Infrastructure cost is a variable and needs to be tracked per feature.
- 2Docker solves the inconsistent-environment problem. The same image runs the same way on a dev's machine and in production — 'it works on my machine' is no longer an excuse.
- 3The staging environment exists to protect production. A bug caught on staging is far cheaper than a bug caught on production.
- 4The CI/CD pipeline automates everything from merging code to deploying. When CI fails, a feature can't be merged — that's a quality safeguard, not an obstacle.
- 5A rollback plan has to exist before a release, not after an incident. A release that ships with a database migration can't be rolled back like a normal deploy.