Keep Your App Online
A project-based journey for AI builders: automate deploys with CI, add health checks and uptime alerts, and rehearse a rollback before you need one.
An app that redeploys on every push, tells you when it goes down, shuts down cleanly, and can be rolled back in one command.
An app already deployed once, and access to its host dashboard. A Git repository with a working deploy.
GitHub + a free host + GitHub Actions. Docker optional; any host's built-in deploy works.
The project
You already have a URL. This journey makes it behave like something you can trust: deploys are automatic, failures announce themselves, shutdowns finish in-flight work, and a bad release can be undone without a scramble.
By the end you will have: push-to-deploy, an alert that fires when the site stops responding, health checks your host can act on, and a rollback you have actually performed once.
Before you start
- A deployed app you can reach at a public URL.
- Admin access to its host, and the Git repository the deploy comes from.
- Deploying AI-Generated Apps to Production open in a tab — it is the checklist this journey walks through in order.
Milestone — Make deploys reproducible
Build: a deploy that starts from a clean checkout with documented commands.
If your deploy only works because of something you installed by hand months ago, it is not reproducible, and the first crisis will be worse than it needs to be. Capture the environment in files.
Do it
- Ask your agent to list every runtime assumption — language version, start command, build step — and write them into the repository.
- Pin the runtime version. A floating
latestturns into a surprise upgrade on the worst day. - If your host supports it, add a container or build config so the environment is declared, not remembered.
Done when a fresh clone can be deployed with only the commands in your README.md. If you containerize, make it secure from the start with How to Write a Secure Dockerfile.
Milestone — Automate the deploy with CI
Build: a pipeline that runs tests and deploys when you push to main.
Manual deploys are fine until they are not: you forget a step at 11pm and ship half a change. CI makes the process identical every time.
Prompt your agent
Add a GitHub Actions workflow that:
- runs on push to main,
- installs dependencies, runs the test suite,
and lints,
- deploys only if tests pass,
- uses the deploy token from repository secrets,
never a hardcoded value.
Show me the workflow file and which repository
secrets I need to create.Done when a small commit reaches production without you touching the host dashboard, and a deliberately failing test blocks the deploy. Start from How to Set Up a CI/CD Pipeline With GitHub Actions; What Is CI/CD? explains why the test gate matters more than the automation.
Milestone — Get configuration out of the code
Build: every environment value read from configuration, with an example file.
The deploy is the moment wrong config hurts most, because a missing variable fails in production rather than on your laptop.
Do it
- Move database URLs, API keys, and session secrets into environment variables on the host.
- Add a committed
.env.examplewith dummy values so the required list lives in Git. - Delete any real secrets from the repo and re-issue anything that was ever committed.
Done when the app boots with only the host’s environment variables set, and a repo search finds no live keys. Read Why Do .env Files Keep Leaking Secrets? and How to Scan Your Codebase for Hardcoded Secrets.
Milestone — Add health checks and graceful shutdown
Build: a health endpoint your host can poll, and a shutdown that finishes in-flight requests.
Hosts restart and replace your app constantly. Whether that looks like a routine event or a burst of 502s depends on these two things.
Prompt your agent
Add two endpoints to the app:
- GET /healthz: returns 200 only if the app can reach
the database; 503 otherwise.
- GET /readyz: returns 200 when the app is ready to
accept traffic.
Also handle SIGTERM: stop accepting new requests, finish
in-flight ones, close the database pool, then exit within
ten seconds.
Show me the handler and how to test it locally.Done when stopping the server mid-request lets that request finish, and /healthz returns 503 when you point it at a bad database URL. See What Is a Health Check? and What Is Graceful Shutdown?.
Milestone — Find out before your users do
Build: an external uptime check with an alert channel you actually read.
This is the highest-value hour of the journey. Nobody should have to tell you your site is down.
Do it
- Sign up for a free uptime monitor and point it at
/healthz. - Send alerts to a channel you see — email or phone, not a dashboard.
- Test the alert by pausing the app and confirming the notification arrives.
Done when you have seen a real “site is down” alert and a matching “recovered” alert. How to Get Alerted When Your Site Goes Down and What Is Uptime Monitoring? cover the options and the traps.
Milestone — Rehearse a rollback
Build: a documented one-command rollback, performed once on purpose.
A rollback plan you have never run is a hypothesis. Rehearse it while nothing is on fire.
Do it
- Ask your agent to document how to return to the previous version — a git revert that redeploys, or the host’s promote-previous button.
- Deploy a small, harmless change.
- Roll it back using the documented method and time how long it took.
Done when the site is back on the old version in under five minutes and your README.md records the exact commands. How to Roll Back a Bad Deploy and What Is Zero-Downtime Deployment? are the reference.
Ship checklist
- A clean checkout deploys from documented commands alone.
- Tests gate the deploy in CI.
- No secrets in the repo;
.env.examplelists what is needed. -
/healthzreflects real dependency health, not just process liveness. - SIGTERM finishes in-flight work.
- An external monitor alerts you and you have seen it fire.
- A rollback has been rehearsed and timed.
- Domain and TLS expiry are on a calendar or a monitor — How to Monitor Domain and Certificate Expiry.
Where this journey goes wrong
- Deploying by hand. The one time you skip a step is the one time it breaks.
- Monitoring only the process. Liveness without dependency checks reports healthy while the database is unreachable.
- Dropping requests on restart. No SIGTERM handler means every deploy is a mini-outage.
- Secrets in the repo. The most common way small projects get compromised.
- An untested rollback. The first time you use it should not be during an incident.
FAQ
Do I need Kubernetes or containers for this?
No. One app on one host with a Git-triggered deploy covers every milestone here. Add containers when you need reproducible builds or have multiple services, but they are not what keeps a small site online.
What is the most valuable step in this journey?
The uptime alert. A silently down site is the most expensive failure for a small project, because you hear about it from a user. An external check that reaches you is ten minutes of work and changes the whole project’s reliability.
Related guides
- How to Debug a Crash-Looping Container — for when the host keeps restarting your app.
- Why Should Servers Always Use UTC? — so logs and schedules agree across machines.
- What Is Log Rotation? — before the disk fills and takes the site down.
- Journey: Run a Security Pass Before Real Users — the next hardening step.
- Journey: Make Slow Work Reliable — when requests start timing out.