This is a rewrite of my earlier article, Troubleshoot Postgres clusters easily with Ivory, first published on Medium. Ivory has changed a lot since then, so I've brought the whole story up to date with what it can do today.
When your elephant suddenly takes a nap, you rush to its side to make sure it's doing okay. 🐘
That's how my original article started, when I first introduced Ivory — a tool to get to your elephant's side as fast as possible. Back then it was a small helper for Postgres clusters running Patroni: an overview, a few Patroni buttons, some saved queries and pgcompacttable. Some things in that article are simply not true anymore — Ivory supports Postgres TLS now, it watches plain Postgres replication too, and it now reads the machine behind each node too, so the extra SSH session is gone. So here's the same story, retold the way Ivory looks today.
Why Ivory exists
I'm a developer who supports Postgres clusters with Patroni as the failover system, and managing many of them in different places was exhausting. So I built the tool I wanted to use in my daily work.
These are the problems it set out to solve, and they haven't gone anywhere:
-
Patroni's CLI and API are hard to remember.
patronictlon the right host, the right config file, the right flags — every time. -
Troubleshooting Postgres means running specific queries. Which
pg_stat_*view was it again, and what do I join it with? - Many clusters means many terminals. Copy-pasting the same commands between hosts and clusters is slow and error-prone.
And a few more I've collected over the years:
- "Is it Postgres, or the machine?" Half the incidents are a full disk, a busy CPU or a noisy neighbour — and checking that means yet another SSH session.
- Not every cluster runs Patroni. Sometimes it's a plain primary with a couple of standbys, and you still want to see it.
- Setting up a test cluster takes too long. Three nodes, etcd, Patroni config, replication… just to try something.
So, how does Ivory solve them?
First: one overview of every cluster
Ivory shows all your clusters in one list, each node coloured by its role — green for the leader, blue for replicas — with warning icons when something's off. Tag your clusters (prod, staging, team-a…) and filter by them.
Adding a cluster takes seconds. Type its nodes, or give Ivory just one node and let it detect the rest: one call to Patroni's /cluster returns every member, with the names Patroni gives them.
Open a cluster and you get the overview of every node:
- Role — leader or replica, with synchronous replicas marked
- State — running, streaming, stopped, failed…
- Lag — bytes behind the leader, with a warning past 50 MiB
- Pending restart, scheduled restart or switchover, the timeline, whether the cluster is paused
- Tags — everything you set on the member in Patroni's own config
And warnings that actually catch mistakes. A node that's in your config but not in Patroni's answer is flagged. So is a member Patroni reports that you never configured. And because each node reports its Patroni scope, a node that belongs to a different cluster is flagged too — instead of looking like a perfectly healthy member of yours.
Secondly: HA operations in one click
Every Patroni operation is a button:
| Operation | When to use |
|---|---|
| Switchover | Planned leader change — to a replica you pick, or one Patroni picks. Can be scheduled. |
| Failover | Forced promotion when the leader is gone. |
| Restart | Restart Postgres on a node. Can be scheduled. |
| Reinitialise | Wipe a replica and re-clone it from the leader. |
| Reload | Apply config changes that don't need a restart. |
| Pause / Resume | Switch Patroni's automatic failover off for maintenance, and back on. |
Patroni's dynamic configuration is editable right there too, as a partial patch: change only what you need, and the Pending Restart flag shows you which nodes need a restart to apply it.
No Patroni? Ivory also supports plain Postgres streaming replication — a primary and its standbys, no HA tool in between. It reads roles with pg_is_in_recovery(), replication from pg_stat_replication and pg_stat_wal_receiver, and warns about a standby that isn't streaming or a replication slot that's about to lose its WAL. You can promote a standby (pg_promote()), reload and view the config. Switchover, restart and pause need an HA tool, so for those there's Patroni.
Third: the right query, without remembering it
Every node has a query builder with saved troubleshooting queries, organised by category: Activity (long-running queries, locks, idle connections), Replication (lag, slots, WAL senders and receivers), Bloat, Statistics (autovacuum, cache hit ratio…) and more. Switch between nodes and clusters, and send the same query with one click.
Some nice details:
- Labels tell you where a query belongs: Database Sensitive, Master Only, or Replica Recommended for the heavy ones you shouldn't run on the leader.
-
Prepared statements — put
$1,$2in your SQL, name them, and fill in values at run time. - Your own queries — create custom ones, or edit a system query to fit your setup.
- A free console for anything ad hoc, plus a history of your recent queries.
-
Running queries with cancel and terminate buttons — for that one
SELECTthat's been running since lunch. - A dashboard with databases, connections, sizes and uptime.
Fourth: pgcompacttable, built in
Ivory still ships pgcompacttable to clean up bloated tables. It compacts tables and rebuilds indexes in small batches with only ROW EXCLUSIVE locks — unlike VACUUM FULL, it's safe on a busy production database.
Ivory runs it as a background job on the leader: pick the database, filter the tables, set a delay between batches, and watch its output live. The bloat estimation queries sit right next to it, so you can measure before and after.
Moreover, Ivory simplifies…
- The machine behind each node. Give Ivory an SSH key and every node shows its VM: CPU, memory, network, processes, and any log file streamed live. No agent on your hosts — just SSH.
- Containers. If Postgres runs in Docker, see its logs, inspect it, start, stop or restart it.
- Deploying a new cluster. Pick a template, fill in the hosts, press Deploy. The shipped templates run Zalando's Spilo (PostgreSQL 18 with Patroni) on three machines — or all three nodes on one machine for a test environment. Need etcd for Patroni? There's a template for that too. Plain Postgres replication templates are included as well.
- Password and key management. Passwords and SSH keys live in Ivory's vault, encrypted, and are reused across clusters.
- Certificates and TLS. Add certificates once and use them for both Patroni's API and the Postgres connection, including mutual TLS.
- Teams. Sign in with Basic, LDAP or OIDC, and give every user exactly the permissions they need — one permission per action.
- Your phone. The UI works on mobile, so the 3 a.m. check doesn't need a laptop.
- Backups of Ivory itself. Export your clusters, queries and permissions and import them on another instance.
And now, your AI agent can help too 🤖
Ivory has a built-in MCP server. Connect Claude, Cursor, Codex or any MCP client, and ask in plain words:
"Why is replica 2 in prod lagging?"
"What is blocking queries on the leader? Don't kill anything, just explain."
"Switch the leader to patroni3 — check it's caught up first, and ask me before doing it."
The agent works through Ivory, so it sees only the tools your user has permission for, and your passwords never pass through its context. A view-only user gets an agent that can diagnose everything and change nothing. Setup takes two minutes: Settings → Integrations → MCP Server.
Try it
Ivory is one Docker container with no dependencies:
docker run -p 80:80 --restart always veegres/ivory
Open http://localhost, go through the setup wizard, and add your first cluster. Use it as a personal tool on your laptop, or run it on a VM as a shared service for your whole team.
Ivory has also grown beyond Postgres — it now looks after etcd, Redis, ClickHouse, MongoDB and ZooKeeper the same way. But Postgres is where it started, and it's still where it's strongest.
If Ivory saves you some time, give it a ⭐ on GitHub — it helps other people find it and keeps me building it. Feedback, issues and ideas are always welcome.
Treat your elephants with kindness and respect, and they will show you the way 😉 — that was the last line of the original article, and it still is.
Useful links:



Top comments (0)