Databases & performance · 2026

Your query was instant at launch.
At 50,000 rows it takes 8 seconds.

Most slow indie-SaaS apps are not slow because of traffic. They are slow because Postgres is scanning the whole table. Here is how to find it and fix it tonight.

Catch the slowdown before your users do.

Belmo's AI log monitoring notices when response times keep degrading and tells you on Telegram in plain English, before a customer emails you about it.

No credit card required 1 service free forever AI log monitoring Telegram alerts in plain English
Frequently asked

Quick answers

Why did my query get slow without any code change?

The table grew. Without a matching index, Postgres reads every row to find the few you asked for, and that cost grows with the table. At forty rows the full scan is the fastest option. At fifty thousand it is the slow one, and nothing alerts you when you cross that line.

How do I find which Postgres query is slow?

Set log_min_duration_statement to around 500 milliseconds so Postgres logs every query slower than that, with its parameters. After a day of real traffic you have a list of the worst queries ranked by real production time.

How do I read EXPLAIN ANALYZE output?

Look for Seq Scan versus Index Scan. A slow query typically shows Seq Scan with a large actual time and a Rows Removed by Filter count close to the size of the table: Postgres read everything to return a handful of rows.

Does Postgres index foreign keys automatically?

No. Postgres indexes primary keys and unique constraints, not foreign key columns. ORMs join on foreign keys constantly, so indexing them often speeds up pages you did not know were slow.

Why is Postgres not using my index?

Common causes are wrapping the column in a function, like lower(email), which needs an expression index, and leading wildcards like LIKE '%term', which a normal index cannot serve. On small tables Postgres may also correctly decide a sequential scan is faster.