# How Render handles deploy failures

- Date: 2026-04-01T10:21:38.636Z
- Tags: Deployment, Platform, observability, guides
- URL: https://render.com/articles/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](https://render.com/docs/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](https://render.com/docs/build-pipeline), 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](https://render.com/docs/health-checks) 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](https://render.com/docs/rollbacks) behavior.

For [background workers](https://render.com/docs/background-workers), which don't serve HTTP traffic, Render relies on process uptime and exit codes instead of health checks.

```mermaid
sequenceDiagram
    participant Git as Git Repository
    participant Build as Render Build System
    participant Render as Render Platform
    participant Live as Live Instance (Old)
    participant New as New Instance
    participant LB as Load Balancer

    Git->>Build: Push triggers deploy
    Build->>Build: Execute Build Command
    alt Build Fails
        Build--xGit: Mark Deploy Failed (Live instance untouched)
    else Build Succeeds
        Build->>New: Start Application
        New->>New: Bind to Port
        Render->>New: Ping Health Check Path
        alt Health Check Fails/Timeouts
            Render--xNew: Destroy New Instance
            Render--xGit: Mark Deploy Failed
            Note over LB, Live: Traffic continues to Live Instance (Zero Downtime)
        else Health Check Passes (200 OK)
            Render->>LB: Update Routing
            LB->>New: Route Traffic to New Instance
            Render->>Live: Spin Down Live Instance
        end
    end
```

A minimal health check endpoint in Express looks like this:

```javascript
const express = require('express');
const app = express();

app.get('/health', (req, res) => res.status(200).send('OK'));

app.listen(process.env.PORT || 10000, '0.0.0.0');
```

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](https://render.com/docs/notifications): email, [Slack](https://render.com/docs/slack-integration), and custom [webhooks](https://render.com/docs/webhooks).

Webhooks deliver a structured JSON payload to your endpoint whenever a deploy event occurs. The payload for a failed deploy looks like this:

```json
{
  "type": "deploy_ended",
  "timestamp": "2025-02-25T16:22:19.979294509Z",
  "data": {
    "id": "evt-cuuuses015js70180jk0",
    "serviceId": "srv-cukouhrtq21c73e9scng",
    "serviceName": "my-service",
    "status": "failed"
  }
}
```

You can use the event's `data.id` with the [Render API](https://api-docs.render.com/reference/retrieve-event) 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](https://www.standardwebhooks.com/#resources) 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](https://render.com/docs/cli) with `render logs`. Logs show you exactly where the build or startup failed.

The [MCP server](https://render.com/docs/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](https://render.com/docs/llm-support) packages this into a step-by-step playbook for troubleshooting deployments.

For common failure patterns, see [Troubleshooting your deploy](https://render.com/docs/troubleshooting-deploys).

## 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 `SIGTERM` signal. If your app doesn't intercept it and drain in-flight requests gracefully, those requests get dropped. Implement a [graceful shutdown handler](https://render.com/docs/graceful-shutdown) 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 `healthCheckPath` for every web service that checks real dependencies
- Set up [notifications](https://render.com/docs/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](https://render.com/docs/cli) or [MCP server](https://render.com/docs/mcp-server) to tail logs and inspect failures from your terminal or editor

## FAQ

###### What happens to my live app when a deploy fails on Render?

Nothing. Your existing live service continues running exactly as it was. Render never modifies or replaces the running instance until the new one passes health checks. If the build fails or health checks don't pass within 15 minutes, Render discards the new instance and keeps routing traffic to the previous working deploy.

###### How do I configure health checks on Render?

Set the `healthCheckPath` field in your `render.yaml` or on your web service's Settings page in the [Render Dashboard](https://dashboard.render.com). The path should point to an endpoint that returns a 200 status code when your application is ready to serve traffic. For details, see [Health checks](https://render.com/docs/health-checks).

###### Can I manually roll back to a previous deploy?

Yes. In the Render Dashboard, go to your service's Deploys page and click Rollback on any previous successful deploy. This triggers a new deploy using the code and configuration from that earlier commit. See [Rollbacks](https://render.com/docs/rollbacks) for details.

###### How do I get notified when a deploy fails?

Configure [notifications](https://render.com/docs/notifications) in the Render Dashboard. You can receive failure alerts via email, [Slack](https://render.com/docs/slack-integration), or custom [webhooks](https://render.com/docs/webhooks). Webhooks deliver structured JSON payloads you can use to trigger CI/CD workflows or alert your team in other tools.

###### Why does my deploy fail even though it builds successfully?

If the build succeeds but the deploy still fails, the issue is usually at startup. Common causes include: your app not binding to the `PORT` environment variable, a missing environment variable that crashes the process, a database connection that can't be established, or the health check endpoint not returning a 200 within the 15-minute window. Check your deploy logs in the Render Dashboard or with `render logs` via the [CLI](https://render.com/docs/cli).

###### What is the health check timeout on Render?

Render gives your health check endpoint 5 seconds to respond to each individual check. If the new instance fails all health checks for 15 consecutive minutes after startup, Render cancels the deploy and keeps the previous instance running. See [Health checks](https://render.com/docs/health-checks) for full details.


