Back to news

PostgreSQL Tips for Production Web Apps

PostgreSQL tips we picked up running production web apps. Indexing, query optimization, connection pooling.

PostgreSQL is our go-to database at IT Family. It's powerful, reliable, and incredibly capable. But it rewards teams that take time to understand its performance characteristics. After years running production apps on Postgres, here are the tips we wish someone told us on day one.

Index Strategically, Not Everywhere

Adding indexes is the first thing devs reach for when queries slow down. But over-indexing hurts just as much as under-indexing. Every index slows down writes and eats storage. Start by checking your actual query patterns with pg_stat_statements. Focus on columns in WHERE clauses, JOIN conditions, and ORDER BY. Use composite indexes when queries filter on multiple columns. And try partial indexes for queries that only hit a subset of rows. They're smaller and faster.

Use EXPLAIN ANALYZE Religiously

Stop guessing why a query is slow. Run EXPLAIN ANALYZE and actually read the output. Look for sequential scans on large tables, nested loop joins where hash joins would be better, and row estimate mismatches (stale statistics). Run ANALYZE on tables after bulk inserts or deletes so the query planner stays smart. We check the query plan for every new query that hits production.

Connection Pooling is Non-Negotiable

PostgreSQL creates a new process for each connection. So 200 concurrent connections = 200 OS processes eating memory. In production with bursty traffic, this can exhaust resources fast. We put PgBouncer in transaction pooling mode in front of every production database. It slashes the active connection count while handling thousands of concurrent requests. If you run Postgres without a connection pooler, you're leaving performance on the table.

Optimize Your Data Types

Small data type choices compound at scale. Use UUID v7 instead of v4 for primary keys if you need sortable IDs. They're time-ordered, so B-tree indexes stay efficient. Use timestamptz, not timestamp, to dodge timezone bugs. Use text instead of varchar(n) unless you genuinely need length enforcement. And try JSONB columns for semi-structured data instead of dozens of nullable columns. Just make sure you index the fields you query.

Monitor Slow Queries in Production

Enable pg_stat_statements and set log_min_duration_statement to catch queries above a threshold (we start at 200ms). Review slow query logs weekly. Most performance problems come from a handful of queries that get worse as data grows. Catching them early beats debugging a production fire. Pair this with pg_stat_activity to spot long-running transactions and lock contention.

PostgreSQL is a beast of a database. But it works best when you understand how it thinks. These are lessons from real production workloads. Even implementing a few of them can noticeably improve your app's reliability and speed.