Health Checks
Configure post-deployment health verification to ensure your application is running correctly.
After every deployment, HostFn verifies that your application is running and responding to requests. If the health check fails, HostFn automatically rolls back to the previous deployment.
How Health Checks Work
HostFn runs health checks on the server using curl against your application's health endpoint:
curl -sf http://localhost:{port}{path}The check runs over SSH on the remote server, hitting localhost directly. This means the health check works even before Nginx is configured or DNS is set up.
A health check is considered passing when curl returns exit code 0 (which requires an HTTP 2xx response due to the -f flag). Any non-2xx response or connection failure is treated as a failure.
HostFn retries the health check multiple times with a configurable interval, giving your application time to start up.
Configuration
Configure health checks in your hostfn.config.json:
{
"health": {
"path": "/health",
"timeout": 60,
"retries": 10,
"interval": 3
}
}| Field | Type | Default | Description |
|---|---|---|---|
path | string | "/health" | HTTP path to check on the application |
timeout | number | 60 | Overall timeout in seconds |
retries | number | 10 | Number of health check attempts before giving up |
interval | number | 3 | Seconds to wait between retry attempts |
With the default settings, HostFn will attempt the health check up to 10 times, waiting 3 seconds between each attempt, for a maximum of 30 seconds of polling.
Implementing a Health Endpoint
Your application needs to expose an HTTP endpoint that returns a 2xx status code when healthy. A minimal implementation:
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});Recommended: Deeper Health Checks
For production applications, consider checking downstream dependencies in your health endpoint:
app.get('/health', async (req, res) => {
try {
// Check database connectivity
await db.execute(sql`SELECT 1`);
// Check Redis if applicable
await redis.ping();
res.json({
status: 'ok',
uptime: process.uptime(),
timestamp: new Date().toISOString(),
});
} catch (error) {
res.status(503).json({
status: 'error',
message: error.message,
});
}
});This approach ensures that your application is not only running but can actually serve requests.
Health Check During Deployment
During deployment, the health check runs as Phase 6:
── Health Check ──
⠋ Health check attempt 1/10...
⠋ Health check attempt 2/10...
✔ Health check passedIf all retries are exhausted without a successful response:
── Health Check ──
⠋ Health check attempt 1/10...
⠋ Health check attempt 2/10...
...
✗ Health check failed
── Rolling Back ──
✔ Rolled back to previous deploymentAuto-Rollback on Failure
When a health check fails, HostFn triggers an automatic rollback:
- The previous
dist/directory is restored from the backup created earlier in the deployment - PM2 is reloaded with the restored files
- The deployment is marked as failed
This ensures your application stays available even when a new deployment has issues.
Tuning Health Check Settings
Slow-Starting Applications
If your application takes a long time to start (loading large datasets, warming caches, etc.), increase the retries and interval:
{
"health": {
"path": "/health",
"timeout": 120,
"retries": 20,
"interval": 5
}
}This gives your application up to 100 seconds to become healthy.
Fast-Starting Applications
For lightweight applications that start quickly, you can reduce the wait time:
{
"health": {
"path": "/health",
"timeout": 15,
"retries": 5,
"interval": 2
}
}Custom Health Path
If your application uses a different path for health checks, configure it:
{
"health": {
"path": "/api/status"
}
}Best Practices
- Always implement a
/healthendpoint -- even a simple one that returns200 OKis better than none - Keep health checks fast -- the endpoint should respond within a few hundred milliseconds
- Check critical dependencies -- database connections, external services your app cannot function without
- Do not check optional dependencies -- if your app can work without Redis caching, do not fail the health check when Redis is down
- Return meaningful responses -- include status information in the JSON body for debugging