Transactions Around HTTP Calls in Postgres: Don't
Wrapping a transaction around an external API call sounds careful and is actually one of the worst patterns in production database code.
Notes for the problems that show up after launch: bad plans, awkward migrations, index debt, vacuum pressure, replica lag, and the small decisions that make PostgreSQL easier to operate.
Wrapping a transaction around an external API call sounds careful and is actually one of the worst patterns in production database code.
Backups only matter if restore is rehearsed. The real work is choosing RPO/RTO, preserving WAL, testing restores, and knowing what data you can afford to lose.
Most application-side retry logic is wrong. It either retries everything (and corrupts data) or nothing (and surfaces transient failures to users). Here is the right framework.
A batch job that worked fine in dev can saturate production. The fixes are not exotic — chunk size, lock duration, retry budget — but most teams skip them.
Using a Postgres table as a job queue used to be a recipe for contention. SKIP LOCKED makes it tractable. Here is the pattern that actually scales.
Advisory locks are useful when the database cannot infer the thing you are protecting. They are also dangerous when session scope, pooling, and lock ordering are treated casually.
Arrays are a Postgres feature that can simplify code and a feature that can lock you into bad design. Here is the rule I use to decide when to reach for them.
JSONB is great for things that genuinely vary per row. It is wrong for things that are stable. Most teams use it for both, and pay for it in queries that should have been simple.
WAL problems usually look like disk problems too late. Monitor generation rate, checkpoints, archiving, replication lag, and slot retention before pg_wal owns the incident.
Use NUMERIC when exactness is the product contract. Use DOUBLE PRECISION when measurement error is already part of the domain and speed matters more than decimal identity.
Postgres full-text search is great for the cases it covers and frustrating for the cases it doesn't. Knowing where the line is saves a year of trying to make it do what Elasticsearch does.
CITEXT is a good fit when a column is almost always compared case-insensitively. It is not a universal Unicode answer, and it is not free.