F FreeCronJob
← Blog

How to Monitor PostgreSQL Replication Lag with a Web Cron Job

How to Monitor PostgreSQL Replication Lag with a Web Cron Job

PostgreSQL replication lag can grow quietly until a read replica serves stale data, a failover target falls behind, or maintenance becomes risky. A lightweight web cron check gives you an independent way to measure lag on a schedule and alert before the gap becomes operationally significant.

This guide shows how to expose a small authenticated health endpoint, schedule it safely, choose meaningful thresholds, and avoid alerts that create more noise than value.

What replication lag actually tells you

Streaming replication sends write-ahead log records from a primary PostgreSQL server to one or more replicas. Lag appears when a replica receives, replays, or applies those records more slowly than the primary produces them. A brief delay during a burst may be harmless; a sustained or growing delay can indicate network congestion, heavy queries on the replica, storage pressure, a paused recovery process, or insufficient capacity.

Do not reduce the check to a single “up or down” result. A useful monitor records both the current lag and whether the replica is still making progress.

Choose the right measurements

  • Replay delay: the time between the latest transaction on the primary and the latest transaction replayed on the replica.
  • Write-ahead log distance: the byte difference between the primary location and the replica replay location.
  • Replica activity: whether the WAL receiver and recovery process are active.
  • Trend: whether lag is shrinking, stable, or growing across consecutive checks.

Time lag is easiest to explain to an on-call engineer, while byte lag is often better for spotting a backlog during write-heavy periods. Use both when possible.

Build a narrow health endpoint

Create an internal endpoint such as /internal/health/postgres-replication. The endpoint should run a read-only query, compare the result with your thresholds, and return a small JSON response with an appropriate HTTP status. Keep database credentials on the server; never place them in the cron URL.

{
  "status": "ok",
  "replay_delay_seconds": 3,
  "wal_bytes_behind": 184320,
  "replica_replaying": true
}

Return 200 when the replica is healthy and a non-success status only when the condition genuinely requires attention. Protect the endpoint with a long random bearer token or another server-side authentication method, allow only HTTPS, and keep the response free of hostnames, connection strings, or stack traces. The same principles covered in securing web cron endpoints apply here.

Set thresholds that match your workload

A universal threshold does not exist. A reporting replica may tolerate several minutes of lag, while a user-facing read replica may need to stay within seconds. Start with observed normal behavior and define two levels:

  • Warning: lag is above the normal operating range for several checks.
  • Critical: lag threatens your recovery objective or application correctness.

Require two or three consecutive failures before sending an incident alert. This filters short spikes without hiding a real trend. Clear the alert only after the replica has returned to a healthy range for more than one check.

Schedule the web cron check

  1. Create the authenticated health endpoint and test it manually over HTTPS.
  2. Add a new HTTP cron job that calls the endpoint every one to five minutes, depending on your recovery requirements.
  3. Use a timeout shorter than the scheduling interval so slow checks cannot pile up.
  4. Enable failure notifications for non-success HTTP responses.
  5. Record response time and status so you can distinguish database lag from endpoint availability problems.

If the endpoint can run longer than expected, apply the locking and idempotency practices from the guide to preventing overlapping cron jobs. For transient network failures, use the controlled backoff approach described in cron retry strategies.

Avoid common monitoring mistakes

  • Checking only connectivity: a replica can accept connections while replay is stalled.
  • Alerting on one spike: short bursts are normal on many systems.
  • Running heavy diagnostics: the scheduled endpoint should stay cheap and read-only.
  • Exposing sensitive details: return only the measurements needed for monitoring.
  • Ignoring maintenance windows: suppress or annotate expected lag during planned work.
  • Watching only time lag: combine time, bytes, activity, and trend for a clearer diagnosis.

Test the failure path before relying on it

Temporarily lower the warning threshold in a non-production environment or use a controlled test response. Confirm that the cron service records the non-success status, sends the expected notification, and recovers cleanly when the endpoint returns to normal. Document who owns the alert and what the first response should be: check WAL receiver activity, storage latency, long-running replica queries, network health, and the backlog trend.

Turn a simple check into a reliable signal

A web cron monitor does not replace PostgreSQL-native observability, but it adds an independent outside-in signal. When the endpoint is narrow, authenticated, inexpensive, and tuned to real workload behavior, it can detect a stalled or falling-behind replica before stale reads or an unsafe failover surprise your team.