How Render handles deploy failures
A failed deploy shouldn't take down your application. Render is designed so that if something goes wrong during a build or startup, your existing live service keeps running as if nothing happened. This article walks through how that works at each phase of the deploy process: build isolation, health check gating, automatic rollbacks, and failure notifications.
Immutable deployments
Render uses an immutable deployment model. Instead of modifying your running server in place, every deploy provisions a fresh instance from scratch. The new instance only receives traffic after it passes health checks. If it doesn't pass, Render discards it and keeps routing traffic to the previous working instance.
This separation between the new deploy and the live service is what makes zero-downtime deploys possible. Your application stays up regardless of what goes wrong with the new release.
Phase 1: build isolation
A deployment starts in an isolated build environment, completely separate from your production runtime. The build step installs dependencies, compiles assets, and produces the final artifact.
If the build fails (a dependency can't resolve, the build runs out of memory, or a required environment variable is missing), the deploy stops immediately. Render discards the build container and marks the deploy as failed. Your live service is untouched: no changes to the running container, routing, or background processes.
This isolation means bad commits get caught early, before they can affect anything in production.
Phase 2: health checks and automatic rollbacks
If the build succeeds, Render starts the new instance alongside the existing one. Before routing any traffic to it, Render verifies the new instance is healthy.
Your application must bind to the port specified by the PORT environment variable (Render can usually detect if you bind to a different port). Once the process is up, Render pings your health check endpoint and waits for a successful HTTP response (2xx or 3xx, though 200 is safest).
If the health check fails or times out repeatedly over 15 minutes, Render cancels the deploy: it destroys the new instance, keeps the old one running, and marks the deploy as failed. Traffic never shifts to the broken instance. This is the automatic rollback behavior.
For background workers, which don't serve HTTP traffic, Render relies on process uptime and exit codes instead of health checks.
A minimal health check endpoint in Express looks like this:
For a more robust check, verify that your database connection and other dependencies are ready before returning 200.
Phase 3: notifications and webhooks
When a deploy fails, you want to know immediately. Render sends failure notifications through multiple channels that you can configure in the Render Dashboard: email, Slack, and custom webhooks.
Webhooks deliver a structured JSON payload to your endpoint whenever a deploy event occurs. The payload for a failed deploy looks like this:
You can use the event's data.id with the Render API to fetch additional details about the failure. To verify that a webhook originated from Render, validate the webhook-signature header against your signing secret (the Standard Webhooks libraries handle this for you).
Webhooks require a Professional plan or higher.
Debugging failed deploys
When a deploy fails, your first step is checking the deploy logs in the Render Dashboard or through the Render CLI with render logs. Logs show you exactly where the build or startup failed.
The MCP server brings this into your editor: AI assistants like Cursor and Claude Code can read your deploy logs, check service metrics, and help diagnose failures without leaving your coding environment. The render-debug agent skill packages this into a step-by-step playbook for troubleshooting deployments.
For common failure patterns, see Troubleshooting your deploy.
Common mistakes
Render's safety nets depend on your configuration. A few mistakes can weaken them:
- Skipping health checks: Without a
healthCheckPath, Render falls back to basic TCP port-binding verification. It assumes any app that binds to the port is ready, even if your database connection pool hasn't initialized yet. This can cause 500 errors for the first requests after a deploy. Always define an explicit health check endpoint. - Returning 200 without checking dependencies: A health check that returns a static 200 without verifying database or cache connectivity defeats the purpose of the check. If your dependencies aren't ready, the health check should reflect that.
- Not handling SIGTERM: When your old instance shuts down after a successful deploy, Render sends a
SIGTERMsignal. If your app doesn't intercept it and drain in-flight requests gracefully, those requests get dropped. Implement a graceful shutdown handler to close connections cleanly.
Next steps
Render's deploy pipeline is designed to protect your live application at every stage. To make the most of it:
- Define a
healthCheckPathfor every web service that checks real dependencies - Set up notifications so your team knows immediately when a deploy fails
- Implement graceful shutdown handlers to avoid dropped requests during successful deploys
- Use the Render CLI or MCP server to tail logs and inspect failures from your terminal or editor