Monitor application health on Replit by building a /health endpoint that reports uptime, memory, and database connectivity. Use the Resources panel for real-time CPU and RAM graphs, check deployment logs in the Deployments pane for errors, and set up external uptime monitoring with services like UptimeRobot or Betterstack to get alerts when your deployed app goes down.
Monitor Application Health and Uptime on Replit
Deployed applications need monitoring to catch downtime, memory issues, and errors before users notice. Replit provides a Resources panel and deployment logs, but lacks built-in alerting. This tutorial shows you how to create health check endpoints that Replit's deployment system and external monitors can use, view deployment logs for troubleshooting, and set up external uptime monitoring for production applications.
Prerequisites
- A Replit account on Core or Pro plan
- A deployed application on Replit (Autoscale or Reserved VM)
- Basic understanding of HTTP endpoints and JSON responses
- An Express (Node.js) or Flask (Python) application
Step-by-step guide
Build a health check endpoint
Build a health check endpoint
Create a /health endpoint that returns the application's current status. This endpoint serves two purposes: Replit's deployment system uses it for health checks (the homepage must respond within 5 seconds), and external monitoring services poll it to detect downtime. Return a JSON response with the application status, current uptime, memory usage, and timestamps. Keep the endpoint lightweight with no database queries or heavy computation so it always responds quickly, even when other parts of the application are under load.
1// Express.js health endpoint2const express = require('express');3const app = express();4const startTime = Date.now();56app.get('/health', (req, res) => {7 const mem = process.memoryUsage();8 res.json({9 status: 'healthy',10 uptime: Math.floor((Date.now() - startTime) / 1000) + 's',11 timestamp: new Date().toISOString(),12 memory: {13 heapUsed: Math.round(mem.heapUsed / 1024 / 1024) + 'MB',14 heapTotal: Math.round(mem.heapTotal / 1024 / 1024) + 'MB',15 rss: Math.round(mem.rss / 1024 / 1024) + 'MB'16 },17 environment: process.env.REPLIT_DEPLOYMENT ? 'production' : 'development'18 });19});2021app.listen(3000, '0.0.0.0', () => {22 console.log('Server running on port 3000');23});Expected result: Visiting /health returns a JSON response with status, uptime, memory metrics, and environment. The response returns in under 100ms.
Add database connectivity checks to the health endpoint
Add database connectivity checks to the health endpoint
Expand the health endpoint to verify that critical dependencies like the database are reachable. Run a simple query like SELECT 1 to confirm the database connection is alive without putting load on it. If the database check fails, return a degraded status instead of crashing the endpoint. This lets monitoring tools distinguish between a completely down application and one running with degraded functionality. Set a timeout on the database check so a slow database does not cause the health endpoint itself to time out.
1const { Pool } = require('pg');2const pool = new Pool({ connectionString: process.env.DATABASE_URL });34app.get('/health', async (req, res) => {5 const mem = process.memoryUsage();6 const checks = { database: 'unknown' };78 try {9 const dbStart = Date.now();10 await Promise.race([11 pool.query('SELECT 1'),12 new Promise((_, reject) =>13 setTimeout(() => reject(new Error('DB timeout')), 3000)14 )15 ]);16 checks.database = 'connected';17 checks.dbLatency = (Date.now() - dbStart) + 'ms';18 } catch (err) {19 checks.database = 'disconnected';20 checks.dbError = err.message;21 }2223 const status = checks.database === 'connected' ? 'healthy' : 'degraded';2425 res.status(status === 'healthy' ? 200 : 503).json({26 status,27 uptime: Math.floor((Date.now() - startTime) / 1000) + 's',28 timestamp: new Date().toISOString(),29 memory: {30 heapUsed: Math.round(mem.heapUsed / 1024 / 1024) + 'MB',31 rss: Math.round(mem.rss / 1024 / 1024) + 'MB'32 },33 checks34 });35});Expected result: The /health endpoint reports database connectivity status with latency. A healthy response returns 200 with 'connected'. A database failure returns 503 with 'degraded' and the error message.
Monitor resources using the Resources panel
Monitor resources using the Resources panel
Replit's built-in Resources panel shows real-time CPU, RAM, and storage usage for your workspace. Click the stacked computers icon in the left sidebar to open it. While the Resources panel is primarily for the development workspace and not for production deployments, it helps you understand your application's resource profile during development. Watch the graphs while running load tests or normal usage to establish baseline memory and CPU patterns. If CPU consistently maxes out or RAM climbs continuously, address these issues before deploying.
Expected result: The Resources panel shows live graphs of CPU usage, RAM consumption, and storage. You can identify whether your app has stable resource usage or concerning growth patterns.
Access deployment logs for error diagnosis
Access deployment logs for error diagnosis
Deployed Replit apps write logs that you can access from the Deployments pane. Open the Deployments tab and click on your active deployment to see its logs. These logs include stdout and stderr output from your application, startup messages, and error stack traces. When your deployed app crashes or behaves unexpectedly, deployment logs are your first debugging tool. Common issues visible in logs include missing environment variables (secret not set in deployment pane), port binding errors (server not listening on 0.0.0.0), and unhandled exceptions that crash the process.
1// Add structured logging to make deployment logs more useful2function log(level, message, data = {}) {3 console.log(JSON.stringify({4 level,5 message,6 timestamp: new Date().toISOString(),7 ...data8 }));9}1011// Use throughout your application12log('info', 'Server started', { port: 3000 });13log('error', 'Database connection failed', { error: err.message });14log('warn', 'High memory usage', { heapUsed: mem.heapUsed });Expected result: Deployment logs show structured JSON entries with timestamps, severity levels, and contextual data. You can identify errors and trace their cause from the log output.
Set up external uptime monitoring
Set up external uptime monitoring
Replit does not send alerts when your deployed app goes down. Set up an external monitoring service that polls your /health endpoint at regular intervals and sends notifications when it fails. Free options include UptimeRobot (50 monitors free, 5-minute intervals) and Betterstack (free tier with 10 monitors). Configure the monitor to check your deployed app's URL followed by /health, set the expected status code to 200, and configure alert channels like email, Slack, or SMS. This gives you immediate notification when your app becomes unreachable or returns a degraded status.
Expected result: An external service monitors your /health endpoint every 5 minutes. You receive an alert via email or Slack when the endpoint is unreachable or returns a non-200 status code.
Add request logging middleware for traffic analysis
Add request logging middleware for traffic analysis
Add middleware that logs every incoming request with method, path, status code, and response time. This data helps you understand traffic patterns, identify slow endpoints, and catch errors that users experience. Keep the logs lightweight to avoid consuming excessive storage or slowing down responses. In production, consider logging only errors and requests that take longer than a threshold to reduce noise.
1// Request logging middleware2app.use((req, res, next) => {3 const start = Date.now();45 res.on('finish', () => {6 const duration = Date.now() - start;7 const entry = {8 method: req.method,9 path: req.path,10 status: res.statusCode,11 duration: duration + 'ms',12 timestamp: new Date().toISOString()13 };1415 // Log all errors, and slow requests over 1s16 if (res.statusCode >= 400 || duration > 1000) {17 console.log(JSON.stringify({ level: 'warn', ...entry }));18 }19 });2021 next();22});Expected result: The deployment logs show request entries for errors and slow responses. You can identify problematic endpoints and track response times over time.
Complete working example
1const express = require('express');2const { Pool } = require('pg');34const app = express();5const PORT = 3000;6const startTime = Date.now();78// Database connection (if using PostgreSQL)9const pool = process.env.DATABASE_URL10 ? new Pool({ connectionString: process.env.DATABASE_URL })11 : null;1213// Request logging middleware (skip /health)14app.use((req, res, next) => {15 if (req.path === '/health') return next();16 const start = Date.now();17 res.on('finish', () => {18 const duration = Date.now() - start;19 if (res.statusCode >= 400 || duration > 1000) {20 console.log(JSON.stringify({21 level: res.statusCode >= 500 ? 'error' : 'warn',22 method: req.method,23 path: req.path,24 status: res.statusCode,25 duration: duration + 'ms',26 timestamp: new Date().toISOString()27 }));28 }29 });30 next();31});3233// Health check endpoint34app.get('/health', async (req, res) => {35 const mem = process.memoryUsage();36 const checks = {};3738 if (pool) {39 try {40 const dbStart = Date.now();41 await Promise.race([42 pool.query('SELECT 1'),43 new Promise((_, reject) =>44 setTimeout(() => reject(new Error('timeout')), 3000)45 )46 ]);47 checks.database = 'connected';48 checks.dbLatency = (Date.now() - dbStart) + 'ms';49 } catch (err) {50 checks.database = 'disconnected';51 checks.dbError = err.message;52 }53 }5455 const isHealthy = !pool || checks.database === 'connected';5657 res.status(isHealthy ? 200 : 503).json({58 status: isHealthy ? 'healthy' : 'degraded',59 uptime: Math.floor((Date.now() - startTime) / 1000) + 's',60 timestamp: new Date().toISOString(),61 memory: {62 heapUsed: Math.round(mem.heapUsed / 1024 / 1024) + 'MB',63 rss: Math.round(mem.rss / 1024 / 1024) + 'MB'64 },65 checks,66 env: process.env.REPLIT_DEPLOYMENT ? 'production' : 'development'67 });68});6970// Your application routes71app.get('/', (req, res) => {72 res.json({ message: 'Application running' });73});7475app.listen(PORT, '0.0.0.0', () => {76 console.log(JSON.stringify({77 level: 'info',78 message: 'Server started',79 port: PORT,80 timestamp: new Date().toISOString()81 }));82});Common mistakes when monitoring app health in Replit
Why it's a problem: Making the health endpoint perform heavy operations like full database queries or external API calls, causing it to timeout during high load
How to avoid: Keep the health endpoint lightweight. Use SELECT 1 for database checks. Do not call external APIs or run business logic. The endpoint should always respond in under 1 second.
Why it's a problem: Not setting up deployment secrets separately from workspace secrets, causing the deployed app to crash with undefined environment variables
How to avoid: Add all required secrets (DATABASE_URL, API keys) in both the workspace Secrets tool and the Deployment pane. Workspace secrets do not automatically carry to deployments.
Why it's a problem: Relying solely on Replit's Resources panel for production monitoring, which only works in the development workspace and not for deployed apps
How to avoid: Use the health endpoint plus an external monitoring service for deployed apps. The Resources panel is for development-time resource profiling only.
Why it's a problem: Setting monitoring intervals shorter than the Autoscale cold start time, generating false downtime alerts every time the app scales to zero
How to avoid: Set monitoring timeout to 30+ seconds and configure the monitor to require 2-3 consecutive failures before alerting. This eliminates false alarms from cold starts.
Best practices
- Always include a /health endpoint that responds within 5 seconds to satisfy Replit's deployment health check requirements
- Return HTTP 200 for healthy status and 503 for degraded status so monitoring tools can distinguish between states
- Include database connectivity checks in the health endpoint with a timeout to catch slow or dead connections
- Use structured JSON logging with timestamps and severity levels for easier searching in deployment logs
- Set up external uptime monitoring with services like UptimeRobot since Replit does not provide built-in alerting
- Exclude the /health endpoint from request logging middleware to avoid flooding logs with monitoring traffic
- Set monitoring timeouts to at least 30 seconds for Autoscale deployments to account for cold start latency
- Log request duration for all requests and alert on any endpoint consistently taking more than 1 second
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
My Express app is deployed on Replit Autoscale and I need to monitor its health. Show me how to create a /health endpoint with database checks, structured JSON logging, and explain how to set up UptimeRobot for external monitoring.
Add a /health endpoint to this Express app that checks database connectivity and returns status, uptime, and memory usage. Add request logging middleware that logs errors and slow requests. Configure the .replit deployment section with the correct port binding.
Frequently asked questions
Replit provides the Resources panel for development workspace monitoring and deployment logs for production. It does not have built-in alerting, uptime monitoring, or notification systems. Use an external service like UptimeRobot or Betterstack for alerts.
Autoscale deployments scale to zero instances after 15 minutes of inactivity. The first request triggers a cold start that takes 10-30 seconds. Set your monitoring timeout to at least 30 seconds to avoid false failure alerts during cold starts.
Open the Deployments pane in your project workspace and click on your active deployment. The logs tab shows stdout, stderr, and system messages from your deployed application.
Replit's deployment health check times out after 5 seconds. If your homepage or health endpoint exceeds this, the deployment may be marked as unhealthy and fail. Keep the endpoint lightweight and use timeouts on database checks.
Not within Replit itself. Use an external monitoring service that lets you add multiple endpoints. UptimeRobot's free tier supports 50 monitors, enough for most multi-app setups. For enterprise monitoring needs, RapidDev can help set up comprehensive observability across all your deployed applications.
Reserved VM deployments are always on and do not have cold start delays, making them better for health-monitored apps. Autoscale deployments scale to zero, which means monitoring will regularly trigger cold starts and could generate false alerts.
Never log full request bodies, authentication tokens, or user passwords. Log only metadata like request path, status code, error message, and duration. Sanitize error messages to remove database connection strings or API keys before logging.
Yes, through external monitoring services. UptimeRobot and Betterstack both support Slack, Discord, email, SMS, and webhook notifications. Configure the alert channel in the monitoring service after adding your /health endpoint as a monitor.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation