Queries that got slow gradually
Fine at ten thousand rows, painful at ten million. A sequential scan the planner had no alternative to, or a sort spilling to disk because work_mem was never touched.
[ Development ]
Postgres is rarely the problem. How it's used usually is.
Most slow PostgreSQL databases are not short on hardware. They are missing an index, running a query the planner cannot help, holding connections they do not need or carrying years of bloat. I find which one, fix it, and show you the before-and-after plan so you know it was the real cause.
Measured before and after · No changes without a rollback · Written findings
[ Why teams call ]
Almost never one dramatic mistake. Usually a handful of small ones that compound as the data grows.
Fine at ten thousand rows, painful at ten million. A sequential scan the planner had no alternative to, or a sort spilling to disk because work_mem was never touched.
An index on every column, none of them matching the actual WHERE and ORDER BY, and every write paying for all of them.
Hundreds of idle connections from app servers and serverless functions, each costing memory, until Postgres starts refusing new ones at peak.
Autovacuum tuned for a small database, tables several times larger than their live data, and a transaction ID wraparound warning nobody has noticed yet.
A nightly pg_dump that has never been restored end to end, no point-in-time recovery, and no idea how long a restore would actually take.
Postgres 11 or 12 out of support, an upgrade postponed because nobody is sure how long the downtime would be or what might break.
[ How it works ]
Read-only access to pg_stat_statements, the slow query log and the configuration. You get a short written list of the queries costing the most total time, and why, before anything is changed.
Indexes built CONCURRENTLY, queries rewritten, settings adjusted — tested on a copy or staging first, applied in small steps, each with a rollback.
Before-and-after plans and timings for every change, the monitoring queries I used, and notes on what to watch as the data keeps growing.
[ What actually changes ]
Pick the part you need. A single slow endpoint is a perfectly good reason to get in touch.
[ Example engagement ]
A reporting dashboard on a growing orders table, timing out at peak. Three missing composite indexes, one rewritten query and PgBouncer in front of the app servers.
Illustrative example of a typical engagement. Figures vary with the state of your systems and are not a guarantee of a specific outcome.
[ Free · no obligation ]
Paste the query and its EXPLAIN ANALYZE output. You get an honest read on what is wrong and what fixing it would take — often in the same reply.
[ Pricing ]
Tell me the number you have to work with. I'll tell you honestly what's achievable within it — and if it isn't enough, I'll say so before we start rather than halfway through.
Hourly rate $20/hoursmall jobs and ongoing work · fixed price for defined projects
Scope agreed in writing, price agreed in writing, before any work starts. No hourly creep and no invoice you haven't already approved.
For ongoing work — maintenance, monitoring, updates and small changes. Month to month, cancel whenever, no minimum term.
For a single bug, a short task or ongoing tweaks, where writing a full scope would cost more than simply doing the work. Billed in real time, reported in writing.
Budget too tight for the whole thing? I'll often suggest doing the highest-value part first and the rest later, rather than doing all of it badly.
[ Questions ]
Small, well-defined jobs — diagnosing a slow query, reviewing a schema, checking a backup setup — are billed hourly at $20 per hour. Larger work such as a version upgrade or a MySQL migration gets a fixed price, agreed in writing before I start, so the number does not move.
For diagnosis, read-only access is usually enough: pg_stat_statements, the configuration and ideally a recent copy of the schema. Changes are applied through your normal process, or by me on staging first and then production with your sign-off.
Sometimes, but usually not first. In most databases I look at, a few indexes, one or two rewritten queries and connection pooling buy far more than doubling the instance size — and cost nothing per month.
Yes. pg_upgrade with --link keeps downtime to minutes for most databases. Where even that is too long, logical replication to a new cluster lets you cut over in seconds. Either way the upgrade is rehearsed on a copy first and timed.
Yes. The data transfer is the easy part; the real work is data type differences, case sensitivity, auto-increment versus identity columns and queries that relied on MySQL being lenient. I migrate on a copy, run your test suite against it and plan a cutover with a way back.
Yes. Managed Postgres removes the server administration but not the query, index and connection problems. Tuning goes through parameter groups and the provider's tooling rather than postgresql.conf, and I know where each one differs.
Yes, and that tends to give the best result. I explain why each query was slow and what the planner was doing, so your team avoids writing the next one. Changes arrive as normal migrations and pull requests.
I work remotely with clients in the US, UK, Europe, Canada and Australia. Most of the work is asynchronous, and I overlap with your working hours for calls and for any change that touches production.
[ Related services ]
[ Guides on this topic ]
[ Let's talk ]
Describe the symptom or paste the query and its plan. You'll get a straight answer on what is wrong and what fixing it costs — from the person who would actually do the work.