Patroni REST API
Source: https://patroni.readthedocs.io/en/latest/rest_api.html
Patroni uses its REST API during leader races. patronictl uses it for failovers, switchovers, reinitialization, restarts, and reloads. HAProxy and other load balancers use it for HTTP health checks. Monitoring systems can also use it. This page lists the available endpoints.
Health check endpoints
Health check GET requests return an HTTP status code and a JSON document with node status. Use HEAD or OPTIONS instead of GET if you do not need JSON.
The following requests to Patroni REST API will return HTTP status code 200 only when the Patroni node is running as the primary with leader lock:
GET /GET /primaryGET /read-write
GET /standby-leader: returns HTTP status code 200 only when the Patroni node is running as the leader in a standby cluster.GET /leader: returns HTTP 200 if the node holds the leader lock. Unlike the preceding endpoints, it does not distinguish PostgreSQL rolesprimaryandstandby_leader.GET /replica: returns HTTP 200 only if the node isrunning, its role isreplica, andnoloadbalanceis unset.GET /replica?replication_state=<required state>: adds a replication state check toreplica. Usereplication_state=streamingto exclude replicas still catching up through archive recovery.GET /replica?lag=<max-lag>: adds a lag check toreplica. HTTP 200 requires lag below the limit. For performance, Patroni uses DCS cluster.last_leader_operation as the leader WAL position to calculate lag. Specify max-lag as an integer byte count or a readable value, such as 16kB, 64MB, or 1GB.GET /replica?lag=1048576GET /replica?lag=1024kBGET /replica?lag=10MBGET /replica?lag=1GB
GET /replica?tag_key1=value1&tag_key2=value2: also checks customkey1andkey2tags in the YAML tags section. An undefined tag or a value different from the query value returns HTTP 503.The following requests check leader or standby leader status. They ignore custom tags:
GET /?tag_key1=value1&tag_key2=value2GET /leader?tag_key1=value1&tag_key2=value2GET /primary?tag_key1=value1&tag_key2=value2GET /read-write?tag_key1=value1&tag_key2=value2GET /standby_leader?tag_key1=value1&tag_key2=value2GET /standby-leader?tag_key1=value1&tag_key2=value2
GET /read-only: like the above endpoint, but also includes the primary.GET /synchronousorGET /sync: returns HTTP status code 200 only when the Patroni node is running as a synchronous standby.GET /read-only-sync: like the above endpoint, but also includes the primary.GET /quorum: returns HTTP status code 200 only when this Patroni node is listed as a quorum node insynchronous_standby_nameson the primary.GET /read-only-quorum: like the above endpoint, but also includes the primary.GET /asynchronousorGET /async: returns HTTP status code 200 only when the Patroni node is running as an asynchronous standby.GET /asynchronous?lag=<max-lag>orGET /async?lag=<max-lag>: adds a lag check toasynchronousorasync. HTTP 200 requires lag below the limit. For performance, Patroni uses DCS cluster.last_leader_operation as the leader WAL position to calculate lag. Specify max-lag as an integer byte count or a readable value, such as 16kB, 64MB, or 1GB.GET /async?lag=1048576GET /async?lag=1024kBGET /async?lag=10MBGET /async?lag=1GB
GET /health: returns HTTP status code 200 only when PostgreSQL is up and running.GET /liveness: returns HTTP 200 if the heartbeat loop operates correctly. Returns 503 if the last run was more thanttlseconds ago on the primary or2*ttlon a replica. Use this forlivenessProbe.GET /readiness?lag=<max-lag>&mode=apply|write: returns HTTP 200 for a leader or a running, replicating node within the lag limit. The lag parameter limits standby lag and defaults tomaximum_lag_on_failover. Use bytes or readable values, such as 16kB, 64MB, or 1GB. Mode specifies whether WAL must be replayed (apply) or only received (write). The default is apply.As a Kubernetes
readinessProbe, this prevents new pods from becoming ready before they catch up to the leader. With a PodDisruptionBudget, it prevents premature leader termination during rolling restarts. It also excludes replicas that cannot keep up from read-only traffic. Use this endpoint forreadinessProbewhere Kubernetes endpoints cannot support leader elections, such as OpenShift.
The liveness endpoint is lightweight and runs no SQL. Configure probes to start failing around leader key expiration. With the default ttl of 30s, use this example:
Monitoring endpoint
Patroni uses GET /patroni during leader races. Monitoring systems can also use it. Its JSON structure matches the health check endpoints.
Example: A healthy cluster
Example: An unlocked cluster
Example: An unlocked cluster with DCS failsafe mode enabled
Example: A cluster with the pause mode enabled
Retrieve the Patroni metrics in Prometheus format through the GET /metrics endpoint.
PostgreSQL State Values
The patroni_postgres_state metric represents the current PostgreSQL state numerically. Monitoring and alerting systems can use it to track state changes. The PostgresqlState.get_metrics_description() static method generates these values.
| Value | State Name | Description |
|---|---|---|
| 0 | initdb | Initializing new cluster |
| 1 | initdb_failed | Initialization of new cluster failed |
| 2 | custom_bootstrap | Running custom bootstrap script |
| 3 | custom_bootstrap_failed | Custom bootstrap script failed |
| 4 | creating_replica | Creating replica from primary |
| 5 | running | PostgreSQL is running normally |
| 6 | starting | PostgreSQL is starting up |
| 7 | bootstrap_starting | Starting after custom bootstrap |
| 8 | start_failed | PostgreSQL start failed |
| 9 | restarting | PostgreSQL is restarting |
| 10 | restart_failed | PostgreSQL restart failed |
| 11 | stopping | PostgreSQL is stopping |
| 12 | stopped | PostgreSQL is stopped |
| 13 | stop_failed | PostgreSQL stop failed |
| 14 | crashed | PostgreSQL has crashed |
PostgreSQL State Values
Existing numeric values never change, to preserve monitoring compatibility. Future states receive new values.
Cluster status endpoints
- The
GET /clusterendpoint generates a JSON document describing the current cluster topology and state:
GET /historyreturns cluster switchover and failover history. Its format matches history files inpg_wal, with one addition: the timestamp when each timeline was created.
Config endpoint
GET /config: Get the current version of the dynamic configuration:
PATCH /config: Change the existing configuration.
The above REST API call patches the existing configuration and returns the new configuration.
Check that the node applied the configuration. With loop_wait=5, it should log every 5 seconds. Changing “max_connections” requires restart, so the output should show “pending_restart”:
Removing parameters:
To remove or reset a setting, patch it with null:
The above call removes postgresql.parameters.max_connections from the dynamic configuration.
PUT /config: unconditionally replace the complete dynamic configuration:
Switchover and failover endpoints
Switchover
The /switchover endpoint requires a healthy cluster with a leader. It can also schedule a future switchover.
A candidate is optional for /switchover but required for /failover. Without a candidate, all eligible nodes enter the leader race after the leader steps down.
The POST JSON body must include leader. Optional fields are candidate and scheduled_at. Use scheduled_at to schedule a future switchover.
HTTP 200 means switchover or failover completed successfully. HTTP 202 means Patroni scheduled the switchover. Errors return 400, 412, or 503, with details in the response body.
DELETE /switchover can be used to delete the currently scheduled switchover.
Example: perform a switchover to any healthy standby
Example: perform a switchover to a specific node
Example: schedule a switchover from the leader to any other healthy standby in the cluster at a specific time.
Failover
Use /failover for manual failover when no sufficiently healthy node is available. For example, promote an asynchronous standby when all synchronous standbys are unsuitable. A missing leader is not required: failover also works on a healthy cluster.
In the JSON body of the POST request you must specify the candidate field. If the leader field is specified, a switchover is triggered instead.
Example:
Be very careful when using this endpoint, as this can cause data loss in certain situations. In most cases, the switchover endpoint satisfies the administrator’s needs.
POST /switchover and POST /failover endpoints are used by patronictl_switchover and patronictl_failover, respectively.
DELETE /switchover is used by patronictl flush cluster-name switchover.
| Failover | Switchover | |
|---|---|---|
| Requires leader specified | no | yes |
| Requires candidate specified | yes | no |
| Can be run in pause | yes | yes (only to a specific candidate) |
| Can be scheduled | no | yes (if not in pause) |
Failover/Switchover comparison
Healthy standby
A member must pass these checks to enter a switchover leader race or become the selected failover/switchover leader:
- be reachable via Patroni API;
- not have
nofailovertag set totrue; - have watchdog fully functional (if required by the configuration);
- in case of a switchover in a healthy cluster or an automatic failover, not exceed maximum replication lag (
maximum_lag_on_failoverconfiguration parameter); - For a healthy-cluster switchover or automatic failover, check the
check_timelineconfiguration parameter. If it istrue, the member timeline must not be smaller than the cluster timeline; - in synchronous mode:
- In case of a switchover (both with and without a candidate): be listed in the
/synckey members; - For a failover in both healthy and unhealthy clusters, this check is omitted.
- In case of a switchover (both with and without a candidate): be listed in the
Without a leader, manual failover can promote a candidate that fails these checks. It can be absent from /sync in synchronous mode, exceed the lag limit, or have an older timeline than the last cluster timeline.
Restart endpoint
POST /restart: restart Postgres on the specified node. ThePOSTJSON body can contain these optional conditions:- restart_pending: if
true, restart only when configuration changes require it. - role: restart only if the current node role matches the request.
- postgres_version: restart only if the current Postgres version is lower than the requested version.
- timeout: maximum wait for PostgreSQL to accept connections. Overrides
primary_start_timeout. - schedule: future restart timestamp with time zone.
- restart_pending: if
DELETE /restart: delete the scheduled restart.
POST /restart and DELETE /restart endpoints are used by patronictl_restart and patronictl flush cluster-name restart respectively.
Reload endpoint
POST /reload makes Patroni reread and apply its configuration file. This is equivalent to SIGHUP. Changes to parameters such as shared_buffers still require an explicit Postgres restart. Use POST /restart or patronictl_restart.
The reload endpoint is used by patronictl_reload.
Reinitialize endpoint
POST /reinitialize: recreate the data directory on the specified replica. This operation is not allowed on a primary. It removes the data directory and runs pg_basebackup or another replica creation method.
This call may fail while Patroni repeatedly tries to restart a failed Postgres instance. Set {"force":true} in the request body to override this condition.
Set {“from-leader”:true} in the request body to take the basebackup directly from the leader. Use this for reinitialization when all replicas have failed.
The reinitialize endpoint is used by patronictl_reinit.
Was this page helpful?
Thanks—your feedback helps us improve this page.
What got in the way? (optional)