A Real Deployment Walkthrough
Objectives
By the end of this lesson, you should be able to:
- Deploy a containerized application to a platform-as-a-service
- Connect a deployment to a managed database
- Confirm a deployment is actually live, from outside the platform entirely
💡 Why this matters: Every module before this one has been preparation. This lesson is where a containerized, tested, CI/CD-pipelined application actually goes live, reachable by anyone, not just the person who built it.
⚠️ A note on verification: deploying to a real cloud platform requires a real account and real, live infrastructure, neither of which this course’s own sandboxed tooling has access to. The steps below reflect the stable, current, documented deployment flow shared by most modern PaaS platforms (Railway, Render, and similar). Follow these steps yourself, with a real account, to see a live deployment.
Connecting a Repository
Most platform-as-a-service providers start the same way, connecting a GitHub repository directly, once connected, the platform watches for pushes (often just to main) and triggers a new deployment automatically, this is the same trigger Module 4’s CI/CD workflow responds to, many teams let the platform build the container itself, using the exact Dockerfile from Module 3, rather than pulling a pre-built image from a registry.
Provisioning a Managed Database
Rather than running PostgreSQL in a container the platform itself manages (reasonable for local development, Module 3’s Compose file), a production deployment almost always uses a managed database service instead, backups, patching, and failover handled by the platform, not the deploying team. Provisioning one typically takes a few clicks, and produces a DATABASE_URL, this is exactly the value Module 1’s environment validation expects, copied into the platform’s own environment variable configuration, never into a file committed to the repository.
Setting Environment Variables on the Platform
Every secret this track has built, JWT_SECRET, DATABASE_URL, and, starting in Module 7 of this course, a Redis connection string, gets set directly in the platform’s dashboard, or via its CLI, as real environment variables, injected into the running container at deploy time. This is precisely the mechanism Module 1 anticipated, validateEnv() runs the exact same way in production as it does locally, refusing to start if anything required is missing, whether that’s a typo in a local .env file or a variable never set on the platform.
Triggering and Watching a Deployment
A push to main (having passed Module 4’s CI checks) triggers a new deployment, most platforms show real-time build and deploy logs, the same container build process from Module 3 happening on the platform’s own infrastructure, once complete, the platform provides a URL, something like notes-api-production.up.railway.app, reachable from anywhere on the internet, not just the machine that pushed the code.
Confirming It’s Actually Live
curl https://notes-api-production.up.railway.app/api/v1/auth/register \
-X POST -H "Content-Type: application/json" \
-d '{"email":"erin@example.com","password":"sunshine123"}'
The exact same request Course 3’s integration tests sent against a local app instance, now sent over the real internet, to a real, running deployment, a 201 response here is real confirmation, not a test suite passing locally, but the actual application, live, reachable by anyone with the URL.
Try It
- Create an account on a platform-as-a-service (many offer a free tier for exactly this kind of learning), and connect a real GitHub repository containing a small Express app.
- Deploy it, and confirm you receive a live, public URL.
- Provision a managed database on the same platform, and set its connection string as an environment variable, following Module 1’s validation pattern.
- Send a real request to your live URL from your own terminal, using
curl, and confirm you get back a real response, not a local one.
Recap
- Most PaaS platforms deploy directly from a connected Git repository, triggering a new build and deploy on every push to a watched branch.
- Managed databases, provisioned through the platform, produce a connection string set as a real environment variable, never committed to the repository.
- A deployment isn’t confirmed live by a green checkmark in a dashboard, it’s confirmed by a real request, from outside the platform, getting a real response.
Next lesson: production environment variables and custom domains, configuring a live deployment correctly and making it reachable at a real, memorable address.