<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mayur (Do not drink &amp; database) on Medium]]></title>
        <description><![CDATA[Stories by Mayur (Do not drink &amp; database) on Medium]]></description>
        <link>https://medium.com/@drunkdba?source=rss-3319eaf2a6c7------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*n804KKnsIMqfyEz00o81ZA.png</url>
            <title>Stories by Mayur (Do not drink &amp;amp; database) on Medium</title>
            <link>https://medium.com/@drunkdba?source=rss-3319eaf2a6c7------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 23:26:58 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@drunkdba/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[PostgreSQL Santa’s Naughty Query List: How to Earn a Spot on the Nice Query List?]]></title>
            <link>https://drunkdba.medium.com/postgresql-santas-naughty-query-list-how-to-earn-a-spot-on-the-nice-query-list-ebc59b800e2f?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/ebc59b800e2f</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[database-development]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[postgresql]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Tue, 23 Dec 2025 07:01:46 GMT</pubDate>
            <atom:updated>2025-12-26T04:56:03.099Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>Santa doesn’t judge your SQL by intent. Santa judges it by <em>execution plans, logical io, cpu utilization, temp usage, and response time</em>.</p><p>This is a practical conversion guide: common “naughty” query patterns and the simplest ways to turn each into a “nice list” version that is faster, more predictable, and less likely to ruin your on-call holidays.</p><h3>1) Naughty: SELECT * on wide tables (~100 columns)</h3><h3>Why it’s naughty</h3><ul><li><strong>Wider tuples cost more everywhere</strong>: more memory bandwidth, more cache misses, bigger sort/hash entries, more network payload.</li><li><strong>Index-only becomes impossible</strong>: if you request 100 columns, the planner can’t satisfy the query from a narrow index, so you force heap fetches.</li><li><strong>You pay a bigger “spill tax”</strong>: wide rows make sorts/aggregations spill to disk sooner.</li></ul><h3>Extra naughty in the HTAP era</h3><p>Postgres is increasingly “one database, multiple workloads.” Columnar/analytics options (e.g., Orioledb, Hydra Columnar; DuckDB-backed columnstore/engine integrations) make projection discipline even more decisive, because columnar execution reads <em>only the referenced columns </em>so selecting fewer columns directly reduces I/O and CPU.</p><h3>Nice list fixes</h3><ul><li>Always select only what you need.</li></ul><p><strong>Santa verdict:</strong> If you didn’t need the column, don’t fetch it, don’t carry it, don’t ship it.</p><h3>2) Naughty: WHERE tenant_id = $1 ... ORDER BY x LIMIT N that hits the “ORDER BY + LIMIT optimizer quirk”</h3><h3>Why it’s naughty</h3><p>This is a classic planner trap: the optimizer tries to be clever and exploit an index that matches ORDER BY, so it can stop early with LIMIT. But if the filtering predicate is satisfied “elsewhere” (joins, correlations, distribution skew), Postgres may end up scanning far more rows than expected before it finds the first N that qualify. That’s the performance cliff.</p><p>When it goes bad, you see:</p><ul><li>Long response time (scanning deep into an index to find qualifying rows)</li><li>High temp usage if the alternative plan sorts a large intermediate set and spills</li></ul><h3>Nice list fixes :</h3><p><strong>A. “Make the smart optimizer more stupid” (the </strong><strong>+ 0 trick)</strong><br> In some cases, you can deliberately prevent the planner from matching the ORDER BY to an index by turning it into an expression, e.g. ORDER BY x + 0, which can force a different (often better) join order / plan. This is a common workaround used in the wild.</p><pre>SELECT id, tenant_id, x<br>FROM events<br>WHERE tenant_id = $1<br>ORDER BY x+0<br>LIMIT 200;</pre><p><strong>B: Create covering index or Increasing default_statistics_target</strong></p><pre>ALTER TABLE events<br>ALTER COLUMN tenant_id SET STATISTICS 1666;</pre><p><strong>Santa verdict:</strong> LIMIT is only a turbo button if the engine can find the first rows without searching the entire parking lot.</p><h3>3) Naughty: idle-in-transaction (refcursor + client think time)</h3><h3>Why it’s naughty (and this one is pure coal)</h3><p>Idle-in-transaction is a vacuum’s worst enemy:</p><ul><li>It pins an old snapshot, so <strong>autovacuum can’t reclaim dead tuples</strong> that still might be visible.</li><li>Bloat grows, indexes bloat, and eventually your “mystery slowness” appears.</li><li>Meanwhile the backend is doing nothing, just holding the database hostage.</li></ul><p>The refcursor pattern often creates this by design:</p><ol><li>Begin transaction</li><li>Open cursor</li><li>Fetch some rows</li><li>Client does slow work (several minutes to hours)</li><li>Cursor stays open, transaction stays open</li></ol><h3>Nice list fixes</h3><ul><li><strong>Don’t do application think-time inside a DB transaction.</strong> Fetch quickly, commit, process outside, then write back in a new transaction.</li><li>If you must stream: keep the stream continuous, not “fetch then pause.”</li><li>Enforce guardrails:</li></ul><pre>ALTER ROLE app_user SET idle_in_transaction_session_timeout = &#39;30s&#39;;<br>ALTER ROLE app_user SET statement_timeout = &#39;2min&#39;;</pre><p>Quick detector:</p><pre>SELECT pid, usename, wait_event, now() - xact_start AS tx_age, query<br>FROM pg_stat_activity<br>WHERE state = &#39;idle in transaction&#39;<br>ORDER BY 4 DESC;</pre><p><strong>Santa verdict:</strong> A transaction is not a tote bag. Don’t carry it around while you do errands.</p><h3>4) Naughty: mega-CTE chains (WITH a AS (...), b AS (...), c AS (...) ...)</h3><h3>Why it’s naughty</h3><p>Long WITH pipelines can compound rowcount estimation errors. Once estimates are off, everything downstream is at risk: join order, join type, memory sizing, spill behavior. Also a big headache for prod support teams in debugging production functional or data quality issues.</p><h3>Best nice-list option : split into temp tables</h3><p>This gives you:</p><ul><li>a clean pipeline boundary</li><li>the ability to ANALYZE intermediate results (real stats)</li><li>tactical indexes on stages that matter</li></ul><p>Pattern:</p><pre>DROP TABLE IF EXISTS stage1;<br>CREATE TEMP TABLE stage1 AS<br>SELECT ...;<br><br>ANALYZE stage1;<br><br>CREATE INDEX ON stage1 (join_key);<br><br>DROP TABLE IF EXISTS stage2;<br>CREATE TEMP TABLE stage2 AS<br>SELECT ...<br>FROM stage1<br>JOIN ...;<br><br>ANALYZE stage2;<br><br>DROP TABLE IF EXISTS stage3;<br>CREATE TEMP TABLE stage3 AS<br>SELECT ...<br>FROM stage2<br>JOIN ...;<br><br>ANALYZE stage3;<br>.<br>.<br>.<br>.</pre><p>On <strong>“pg_catalog bloat” </strong>issue : in practice, I have seen bigger wins from <strong>good autovacuum tuning</strong> (cost limit/delay, scale factors, number of workers) than from worrying about catalog bloat as a primary performance constraint.</p><p>Also: yes, many of us are still waiting for “true global temp tables someday.” (pgtt extension doesn’t do anything to reduce catalog bloat)</p><p><strong>Santa verdict:</strong> If the planner can’t see the pipeline clearly, give it stages and statistics.</p><h3>5) Naughty: wildcard search LIKE &#39;%foo%&#39; (and friends)</h3><h3>Why it’s naughty</h3><p>A normal B-tree index can only help when the pattern is <strong>anchored at the start</strong> (e.g., col LIKE &#39;foo%&#39;), not when it starts with %.</p><h3>Nice list fixes</h3><p><strong>Fix A: </strong><strong>pg_trgm</strong></p><pre>CREATE EXTENSION IF NOT EXISTS pg_trgm;<br>CREATE INDEX CONCURRENTLY ON docs USING gin (title gin_trgm_ops);</pre><p>pg_trgm provides GIN/GiST operator classes for fast similarity and pattern searches.</p><p><strong>Fix B: Biscuit (newer alternative)</strong><br> Biscuit is an index access method designed specifically for fast LIKE/ILIKE pattern matching and claims to reduce trigram “recheck overhead” for wildcard-heavy queries. Evaluate it on your data and query mix. <br><a href="https://github.com/CrystallineCore/Biscuit">GitHub</a></p><p><strong>Santa verdict:</strong> Leading % turns your index into holiday decoration: pretty, not load-bearing.</p><h3>6) Naughty: functions on indexed columns (WHERE lower(email) = ...)</h3><h3>Why it’s naughty</h3><p>You turned an indexable predicate into an expression; without an expression index, Postgres often can’t use your B-tree index effectively.</p><h3>Nice list fixes</h3><pre>CREATE INDEX CONCURRENTLY ON users ((lower(email)));<br><br>SELECT ...<br>FROM users<br>WHERE lower(email) = lower($1);</pre><p><strong>Santa verdict:</strong> If you wrap the column, index the wrapper.</p><h3>7) Naughty: OR conditions that derail index usage (a = 1 OR b = 2)</h3><h3>Why it’s naughty</h3><p>OR predicates can push the planner into a compromise plan: either scan too much, or pick a strategy that’s great for one branch and terrible for the other.</p><h3>Nice list fixes</h3><p>Split with UNION ALL (careful to preserve semantics):</p><pre>SELECT ... FROM t WHERE a = 1<br>UNION ALL<br>SELECT ... FROM t WHERE b = 2 ;</pre><p><strong>Santa verdict:</strong> OR is two queries wearing one trench coat.</p><h3>8) Naughty: mismatched join types / implicit casts on join keys</h3><h3>Why it’s naughty</h3><p>If join keys don’t match types, you can:</p><ul><li>prevent index usage</li><li>trigger repeated casting on large relations</li><li>get unexpected nested loops</li></ul><h3>Nice list fixes</h3><ul><li>Fix schema types where possible.</li><li>Otherwise cast the parameter, not the column:</li></ul><pre>WHERE t.uuid_col = $1::uuid</pre><p><strong>Santa verdict:</strong> If your join keys can’t agree on a type, they shouldn’t be meeting in production.</p><h3>9) Naughty: missing indexes for join keys / foreign keys (especially on large tables)</h3><h3>Why it’s naughty</h3><ul><li>Joins devolve into large hash builds or repeated scans.</li><li>Deletes/updates on referenced tables become expensive due to referential checks.</li></ul><h3>Nice list fixes</h3><pre>CREATE INDEX CONCURRENTLY ON child (parent_id);</pre><p><strong>Experimental (not for Prod yet) : </strong>Working on an extension to prevent unindexed foreign keys from going in production. <a href="https://github.com/secp256k1-sha256/tenxdev/blob/main/fkhunter/fkhunter_readme.md">FKHunter</a> (Any improvement suggestions are welcome)</p><p><strong>Santa verdict:</strong> Foreign keys without supporting indexes are a gift you gave yourself…. with no receipt.</p><h3>10) Naughty: SELECT DISTINCT as a band-aid for join explosions</h3><h3>Why it’s naughty</h3><p>DISTINCT often hides:</p><ul><li>missing join predicates</li><li>unintended many-to-many relationships</li><li>data modeling issues</li></ul><p>It forces a sort or hash aggregate on an inflated intermediate result.</p><h3>Nice list fixes</h3><ul><li>Fix the join.</li></ul><p><strong>Santa verdict:</strong> DISTINCT is not deodorant.</p><p>If Santa finds your SQL on the Naughty List, don’t take it personally but take it as a to-do list. Pick one offender this week, run EXPLAIN (ANALYZE, BUFFERS), apply the smallest “Nice List” fix, and measure the win. Do that ten times and you won’t just get better latency; you’ll get a calmer pager, and a database that actually feels like it’s on holiday too.</p><p><em>PS: Extra content for holidy season</em></p><p>SQL-Claus Before :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*3H762nGVoo68-ChwbZ7u1A.jpeg" /></figure><p>SQL-Claus Now :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/853/1*tEf9Nunh5SRlCzwKBbS6CQ.jpeg" /></figure><blockquote><strong>AI Generated SQL-Claus Last Christmas vs AI Generated SQL-Claus Today. Some would say AI lost it’s soul in rat race of larger models, previous SQL-Claus meme had a character.</strong></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ebc59b800e2f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The OOM-Killer Summoning Ritual: “Just Increase work_mem”]]></title>
            <link>https://drunkdba.medium.com/the-oom-killer-summoning-ritual-just-increase-work-mem-7afb4b22ec44?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/7afb4b22ec44</guid>
            <category><![CDATA[database-administration]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Fri, 19 Dec 2025 21:57:52 GMT</pubDate>
            <atom:updated>2025-12-20T16:41:28.914Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>You’ve probably seen the incident pattern:</p><ol><li>Postgres backends start disappearing.</li><li>dmesg / journalctl -k shows the kernel OOM killer reaping postgres.</li><li>Someone spots “out of memory” and reflexively recommends: “Increase work_mem.”</li></ol><p>That recommendation is frequently backwards for <em>OS OOM kills</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gz6ienJja1lcfN07KVcj6g.png" /></figure><h3>The linguistic trap: “Out of memory” sounds like “not enough work_mem”</h3><p>work_mem is not “memory for the query.” It is a <strong>base, per-operation</strong> budget for executor nodes like sorts and hash tables <em>before</em> they spill to temporary files. PostgreSQL’s own docs explicitly warn that a complex query can run multiple sort/hash operations concurrently, and many sessions can do this at the same time so total memory can be <em>many times</em> work_mem.</p><p>If you raise work_mem globally, you are raising the ceiling on <strong>many</strong> potential concurrent memory consumers. That can turn “rare spike” into “frequent OOM kill.”</p><h3>OS OOM kill vs “Postgres OOM”: two different failure modes</h3><p>There are two scenarios people accidentally conflate:</p><ul><li><strong>Executor spills to disk (healthy):</strong> Postgres hits a per-node memory budget and writes temp files.</li><li><strong>Kernel OOM kill (host-level failure):</strong> Linux cannot satisfy memory demands (often influenced by overcommit behavior) and terminates a process to keep the system alive.</li></ul><p>In other words: if the kernel is killing Postgres, “give Postgres permission to use even more memory next time” is not a stabilizing strategy.</p><h3>The source code says: work_mem is “allowed memory,” then spill to temp files</h3><p>The tuplesort implementation is blunt about the design: it keeps tuples in memory up to the limit and then switches to temporary “tapes” (temp files) for an external sort.</p><p>A tiny excerpt from src/backend/utils/sort/tuplesort.c (<a href="https://doxygen.postgresql.org/tuplesort_8c_source.html">Doxygen</a>):</p><pre>/* ... memory allowed ... (most pass work_mem) ... */<br>...<br>/* If we do exceed workMem, we begin to emit tuples ... temporary tapes. */</pre><p>This is why “spilling” isn’t synonymous with “misconfigured”. It’s the planned safety valve.</p><h3>Hash nodes can blow past the base: hash_mem_multiplier is literally in the math</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UQ4BEpYZzeIJIwbKF5RL9Q.png" /></figure><p>Hash operations are <em>not</em> capped at work_mem. Postgres computes the hash memory limit as:</p><pre>{<br>    double      mem_limit;<br> <br>    /* Do initial calculation in double arithmetic */<br>    mem_limit = (double) work_mem * hash_mem_multiplier * 1024.0;<br> <br>    /* Clamp in case it doesn&#39;t fit in size_t */<br>    mem_limit = Min(mem_limit, (double) SIZE_MAX);<br> <br>    return (size_t) mem_limit;<br>}</pre><p>That’s get_hash_memory_limit() in src/backend/executor/nodeHash.c. <a href="https://doxygen.postgresql.org/nodeHash_8c.html">Doxygen</a></p><p>The docs also spell out the implications:</p><ul><li>Hash memory limit = work_mem * hash_mem_multiplier</li><li>Default hash_mem_multiplier is 2 (so hash nodes may target ~2× work_mem)</li></ul><p>So if someone says “we set work_mem=128MB, we’re safe,” but you have concurrent HashAgg/HashJoin/Memoize activity, your effective per-node appetite can be meaningfully higher than they think.</p><h3>Why increasing work_mem can make OOM kills more frequent</h3><p>Here’s the mental model that avoids the trap:</p><blockquote><em>work_mem is a </em>multiplier<em> applied by concurrency.</em></blockquote><p>A crude (but useful) worst-case sketch:</p><ul><li>active_sessions = 150 (Typically when a connection pooler is used and peak clients are several thousand then you could end up with few hundred active sessions)</li><li>Conservative assumption that each session runs a query that (at peak) has 2 sorts + 1 hash agg concurrently (3 operations)</li><li>work_mem = 64MB</li><li>hash_mem_multiplier = 2.0</li></ul><p>Then memory budget pressure can look like:</p><ul><li>Sort side: 150 * 2 * 64MB = 19,200MB</li><li>Hash side (approx): 150 * 1 * (64MB * 2) = 19,200MB</li></ul><p>You are already around ~38GB of <em>just</em> sort/hash budgets, before counting:</p><ul><li>backend overhead, memory contexts, connection-local memory</li><li>shared memory, OS cache dynamics, other processes</li><li>parallel query workers (more processes, more operations)</li></ul><p>Now imagine someone “fixes” OOM kills by doubling work_mem to 128MB. That same sketch becomes ~76GB. If the host has 64GB RAM, you didn’t tune performance instead you scheduled the next kill.</p><p>This is why pganalyze’s guidance for frequent OOM errors starts with: <strong>reduce </strong><strong>work_mem</strong> to improve stability, accepting more disk spill as the tradeoff. <a href="https://pganalyze.com/docs/log-insights/server/S5">pganalyze</a></p><h3>A practical playbook: stabilize first, then optimize surgically</h3><p>If you want fewer OOM kills <em>and</em> good performance, separate <strong>global defaults</strong> from <strong>intentional exceptions</strong>:</p><h3>1) Confirm it’s a kernel OOM kill (not just query failure)</h3><ul><li>Check journalctl -k / dmesg for OOM killer messages (process name/PID, reaped memory).</li></ul><h3>2) Make temp spill observable (because spill is the designed safety valve)</h3><p>Turn on temp file logging to see which queries are forcing external sorts / hash batching:</p><ul><li>log_temp_files = 0 (log all temp files) or set a threshold in kB</li></ul><p>Also consider:</p><ul><li>temp_file_limit to prevent a single session from consuming unbounded temp space (it cancels the transaction when exceeded). <a href="https://postgresqlco.nf/doc/en/param/temp_file_limit/">PostgreSQL</a></li></ul><h3>3) Set a conservative global work_mem, then raise it only where justified</h3><ul><li>Keep a modest default that survives peak concurrency.</li><li>For the one reporting job / ETL / admin session that benefits from more memory, use <strong>targeted</strong> increases: <br>SET LOCAL work_mem = &#39;128MB&#39;; inside a transaction <br>or ALTER ROLE reporting_user SET work_mem = &#39;128MB&#39;;</li></ul><p>This preserves cluster stability while still enabling fast “big” queries.</p><h3>4) Use EXPLAIN to validate the tradeoff</h3><p>You want to see spills when needed, not crashes:</p><ul><li>Sort Method: external merge with disk usage is a normal outcome when data exceeds budget.</li><li>Hash nodes show batching when they spill.</li></ul><h3>5) Don’t ignore Linux overcommit behavior</h3><p>In overcommit-heavy configurations, you can get killed before Postgres can gracefully error and log a memory context dump. Cybertec and Postgres community guidance often points to disabling overcommit (or otherwise managing it) to avoid OOM-killer surprise terminations. <a href="https://www.cybertec-postgresql.com/en/what-you-should-know-about-linux-memory-overcommit-in-postgresql/">CYBERTEC PostgreSQL | Services &amp; Support</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aob3sV441xzv-yjGkt0KLw.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7afb4b22ec44" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Application Developers Using AI Is Great For DBA Job Security]]></title>
            <link>https://drunkdba.medium.com/why-application-developers-using-ai-is-great-for-dba-job-security-43042dc0f294?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/43042dc0f294</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[postgresql-database]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Mon, 17 Nov 2025 14:09:53 GMT</pubDate>
            <atom:updated>2025-11-17T14:09:53.510Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>Everyone’s freaking out about AI taking their jobs. Meanwhile, I’m a DBA sitting in the corner thinking: <em>“If programmers of the future are AI agents, companies will need 100x more human DBAs to clean up the mess in production.”</em></p><p>This rant blogpost is my attempt to explain why.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eaORcSJJ5W5gUt2-wAKVsA.png" /></figure><h3>LLMs: Optimizing for the Next Token, Not for Reality</h3><p>Let’s start with the core problem:</p><p>LLMs don’t optimize for <em>truth</em>.<br>They optimize for <em>“what word statistically looks good next?”</em></p><p>Give a model the text:</p><blockquote><em>“Postgres DBAs love”</em></blockquote><p>It might happily continue with:</p><blockquote><em>“Oracle”</em></blockquote><p>From there, it feeds its own output back in and keeps predicting the next token again and again. At no point does it pause and say: <em>“Wait, does this actually represent reality?”</em></p><p>It has no built-in concept of <em>reality</em> or <em>verification</em>. That’s your job.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*885E6nEcHscvnroRStLYmg.png" /></figure><p>As long as this is the operating model, hallucinations are not a bug but they are a <em>feature</em>. They’re what you get when you combine probability with confidence and zero shame. We’re basically wiring a very polite, very confident intern to production and asking it architectural questions.</p><p>What could go wrong?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/833/1*O3Up4OXF44nTpwetoVOOfw.png" /></figure><h3>“Hallucinations” Is Just a Fancy Word for “We Noticed the Lie”</h3><p>I liked one line from an MIT Tech Review piece: “<em>It’s </em>all<em> hallucination, but we just call it that when we notice.”</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OhdXtMQnHYh66JwudVE7EQ.png" /></figure><p>Most of the time, when the answer is “good enough”, we call it “AI magic”.<br> When it’s wrong in a way we understand, suddenly it becomes “hallucination”.</p><p>From a former physics student perspective, this is just non zero probability in action. We already live with quantum tunneling and in theory there’s a very very small but finite probability your laptop falls through the table while reading this paragraph. So the idea that an AI occasionally invents a Postgres feature, a config parameter, or even a fake “Postgres founder” called <em>Michael Stockbroker</em> is not that hard to digest.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1dVjcgIwhGeLRtlYytTUMg.png" /><figcaption>LLMs are Pinnochio’s of modern world.</figcaption></figure><h3>Minimizing Hallucinations ≠ Eliminating Them</h3><p>Yes, there are techniques:</p><ul><li>Retrieval-augmented generation (RAG)</li><li>Better prompts.</li><li>Constraining answers to a small domain.</li><li>Larger training data, new improved models.</li></ul><p>They help. They reduce the probability of a lie.<br>They never turn it into zero. So instead of asking, <em>“How do we make AI always right?” </em>We should be asking, <em>“What happens to systems and teams when AI is </em><strong><em>wrong</em></strong><em> in confident, creative ways?”</em></p><p>That’s where Postgres DBA’s job security enters the chat.</p><h3>Postgres vs AI: Field Reports from the Trenches</h3><p>We don’t need theory. Just look at the real world of Postgres chats, blogs, and forums.</p><h3>1. The Adaptive Optimizer That Doesn’t Exist</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ezbwlx3vz6JtXfqaaQ8kUg.png" /></figure><p>One popular LinkedIn post proudly announced that <strong>Postgres now has an adaptive optimizer</strong>, just like Oracle changing plans mid-execution, magically fixing bad queries at runtime.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hnt2Wqzt6ePAmGU247M5qQ.png" /></figure><p>Reality check:</p><ul><li>Postgres does <strong>not</strong> have Oracle-style adaptive optimizer.</li><li>People migrating from Oracle to Postgres often <em>wish</em> it did.</li><li>Most serious Oracle deployments especially in finance domain don’t enable adaptive optimization in production anyway. They value <em>predictable latency</em>, not “charismatic magic” that wakes up once every blue moon and wrecks your critical workload.</li></ul><p>But somewhere, an LLM saw enough Oracle docs, blogs, and forum posts and decided: <em>“Postgres is a database. Oracle is a database. Adaptive optimizer is cool. Therefore, Postgres now has an adaptive optimizer.”</em></p><p>And now that garbage is in the content pool.</p><h3>2. “Even ChatGPT Failed to Answer This!”</h3><p>From Postgres community chat: user confused about why something wasn’t working.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/848/1*jZTf8twRlsfQAWdKnnZuig.png" /></figure><p>LLM confidently explained that &#39;&#39; (empty quoted whitespace) is the same as NULL.<br>Humans: <em>“No. That’s not NULL. That’s just an empty string. Here’s why.”<br></em>One line from a human fixed it.<br>An LLM left the user more confused.</p><h3>3. TTL Indexes in Postgres? Sure, Why Not</h3><p>Someone shows up: “I read about TTL indexes in Postgres, how do I use them?”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iLdd3uvI1TeWHGzAQEmjxw.png" /></figure><p>Short answer from the community: <em>“You don’t. Postgres doesn’t have native TTL indexes.”</em></p><p>Of course, you <em>can</em> build TTL-like behavior with partitioning and pg_cron schedular based archival/dropping of old, unnecessary partitions. But there’s no single magical TTL index type like in some other databases.</p><p>LLMs, however, happily remix MongoDB + Postgres content into: <em>“Here’s how to create a TTL index in Postgres”</em></p><p>And now we’re babysitting that.</p><h3>4. “Just Tweak the Background Workers in Prod”</h3><p>One of my favorites: AI confidently suggesting users adjust internal Postgres <strong>background workers</strong> in ways no sane human would recommend to any developer.</p><p>This is the kind of advice that:</p><ul><li>Looks sophisticated</li><li>Sounds low-risk</li><li>Is absolutely <strong>not</strong> for casual experimentation on prod instances</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/916/1*2DEF0sgJtoNeVx2O3_4duA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W0D6RB8OF9-DGSmrVVGO9Q.png" /></figure><p>Once that advice leaks into tutorials/blogs, it slowly contaminates future AI training runs. Then the next generation of LLMs produces even more polished nonsense.</p><p><strong>High-quality garbage. With headings.</strong></p><h3>5. LLM induced extra work</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*56rkzTdXLwKcX2MKDB2jSQ.png" /></figure><p>An LLM confidently advises: <em>“Now you should rebuild all indexes to be safe.”</em></p><p>No, you shouldn’t.</p><ul><li>Reindexing everything after a successful upgrade is an <em>unnecessary</em> time sink, risk that adds downtime to upgrade.</li><li>LLM probably got confused with reindexing required on OS update due to <a href="https://www.crunchydata.com/blog/glibc-collations-and-data-corruption">(in)famous glibc issue</a>.</li></ul><p>But sure, if someone blindly follows it, that’s:</p><ul><li>Extra downtime,</li><li>Extra IO,</li><li>Extra DBA hours.</li></ul><h3>6. Two Node Patroni HA with Autofailover 🤡</h3><p><em>“Design a 2-node Patroni HA cluster with auto-failover. DCS, Postgres, Patroni all on just two machines.”</em></p><p>LLM: <em>“Of course! Here’s a step-by-step guide…”</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FRSBrhy-iOl8GuDDUSyrvA.png" /></figure><p>Human DBA: <em>“No. Just… no. You are designing a split-brain machine.”</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/791/1*Q-YZZk2ZIrvtprCIPQ629Q.png" /></figure><p>Because in a network partition with two nodes, both can think they’re the primary. And then you have:</p><ul><li>Diverged writes</li><li>Broken constraints</li><li>Business screaming</li><li>Audit logs full of horror</li></ul><p>Who saves the day?<br>Not the LLM.</p><h3>Data Cannibalism: When AI Starts Eating Its Own Slop</h3><p>Another fun part of this story: <strong>data cannibalism</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/950/1*vaiRPcXD8MK25kVK8h8uHg.png" /></figure><p>As more AI generated content floods the internet:</p><ul><li>That content gets scraped into future training data.</li><li>The model trains on its own previous guesses.</li><li>Errors compound.</li><li>Rare edge cases vanish.</li><li>Details blur and collapse toward generic nonsense.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ju5a4OJSEGB6SBkSr5FpjA.png" /></figure><p>There’s already published work showing that models trained on AI generated data <strong>collapse</strong> over generations. And estimates that we may run out of clean human generated data for training in a few years, depending on how aggressively we keep training new models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x64TuF8WN-J0AoUDrJBKsg.png" /></figure><p>Even worse: those estimates often <em>don’t</em> factor in how much AI slop humans are now posting as their own “blog posts” and “whitepapers”.</p><p>One research paper about Postgres I came across had very clear indicators of being LLM generated fake :</p><ul><li>“In the digital world…” as intro</li><li>AI-generated fake graphs : A misspelling in the chart title but correct text in the caption</li><li>And it credited Postgres to founder “Michael Stockbroker”</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/890/1*YxwG2AQxSxySSLin87u9yg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/890/1*0MUxQmHrskyaRqmEnpf1FA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/625/1*fVchHRQ_EylrWxhJjGrWTw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/666/1*doRezDox0Dom0DLY0FHuxQ.png" /></figure><p>So we’re seeding the future with:</p><ul><li>Invented features</li><li>Incorrect design patterns</li><li>Misleading performance “benchmarks”</li><li>Fake Subject Matter Experts</li></ul><p>This is the stuff going into future model training sets.<br>Enjoy your model collapse.</p><p><strong>Meanwhile, humans DBAs become more valuable, not less.</strong></p><h3>So… What Can AI Safely Do for Postgres?</h3><p>Despite all this, I’m not <strong>anti-Automation</strong>.<br>I’m anti-“AI as a magical production architect”.</p><p>There <em>are</em> areas where narrow AI with <strong>limited scope for creativity</strong> can be useful:</p><h3>1. DB Parameter Tuning (Within Limits)</h3><p>Tools like DBTune that:</p><ul><li>Suggest reasonable shared_buffers, work_mem etc Parameter ranges.</li><li>Maybe even propose changes in a Git-style diff</li></ul><p>This is bounded, repeatable, and easy to verify. Worst case, you roll back a config.</p><h3>2. Index Advisors</h3><p>Systems that:</p><ul><li>Analyze postgres logs, waits and pg_stat_statements</li><li>Suggest candidate indexes</li><li>Estimate bloat and usage</li></ul><p>As long as they stay in “advisor” mode and a human reviews changes before applying, they’re super helpful. Think <strong>pganalyze</strong> style, not “Let the LLM directly CREATE INDEX in prod at 11:55 before Black Friday”.</p><h3>3. Ops Automation</h3><p>Great use cases:</p><ul><li>Alerting on txid wraparound risk</li><li>Growing storage before it fills</li><li>Notifying you when replication lag spikes</li><li>Automating some backup/restore checks</li></ul><p>Basically: if it’s mechanical, measurable, and reversible automation is powerful.</p><h3>Future of AI for DBAs: Expectation vs Reality</h3><p><strong>Expectation:</strong><br>AI agents write all the code, optimize all the queries, run all the operations.<br>DBAs disappear. Everything is self-healing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/916/1*mlQrsp2kBx44jd1fk3sSmQ.png" /></figure><p><strong>Reality:</strong></p><ul><li>AI generates weird schemas, terrible queries, and unsafe designs.</li><li>AI hallucinates Postgres features that don’t exist.</li><li>AI amplifies bad advice from old mailing list threads.</li><li>Startups implement this stuff directly in production.</li><li>Systems break in more creative ways than ever before.</li></ul><p>And then those companies:</p><ul><li>Hire senior DBAs</li><li>Pay more per hour</li><li>Prioritize performance &amp; reliability</li><li>Buy support contracts they previously refused</li></ul><p>So if you’re a DBA worrying about AI taking your job, relax. You’re going to be busy.</p><p>Very, <em>very</em> busy.</p><p>PS: By popular demand, I’ve included some extra AI-generated content. I accept no liability, take zero responsibility, and fully classify the following as <em>AI slop found in the wild</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1005/1*sfbhDMWl5yQd1dgueU2jSw.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43042dc0f294" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ALTER Egos: Me, Myself, and Cursor]]></title>
            <link>https://drunkdba.medium.com/alter-egos-me-myself-and-cursor-3978fd29245f?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/3978fd29245f</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[database-administration]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Tue, 04 Nov 2025 05:56:18 GMT</pubDate>
            <atom:updated>2025-11-04T05:56:18.419Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AGJH6azqsKarnhWk6bBvdA.png" /></figure><p>I pushed the most boring change imaginable, add an index. Our CI/CD pipeline is textbook ==&gt; spin up a fresh DB, run every migration file in <strong>one single transaction</strong>, in sequential manner. If anything hiccups, the whole thing rolls back and the change never hits main. Foolproof autotests.</p><p>Enter The Drama Queen :</p><pre>ERROR: cannot CREATE INDEX &quot;index_name_xyz&quot; on table abcdef_tab<br>because it is being used by active queries in this session</pre><p>This session. Same PID, same transaction. No parallel runner. No second connection. Still blocked.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/522/1*uOap503Ed44D9JwgJiG_1Q.jpeg" /></figure><p>Our schema migration repository structure is as shown above. CI tool will create a fresh DB → execute all scripts chronlogically → one by one → one transaction → one session as a part of an autotest before merging any new code (dml/ddl for schema migration = infra as a code) to main branch.</p><p>Naturally ignoring last part of error message like a seasoned DBA, I accused CI tool of going rogue, maybe someone “optimized” migrations to run in parallel after reading a LLM pep talk about “unleashing concurrency.”</p><p>I printed the PID at the start and end of every file.</p><pre>-- Stamp the migration transaction<br>SELECT &#39;start&#39;, pg_backend_pid(), txid_current();<br>-- ... run all migration steps ...<br>SELECT &#39;end&#39;,   pg_backend_pid(), txid_current();</pre><p>Same PID. Same transaction. Same sadness.</p><p>One of the least talked about but best Postgres feature as a FOSS project is that you can search error message in code base and documentation is excellent.</p><ul><li>In indexcmds.c, PostgreSQL calls CheckTableNotInUse(rel, &quot;CREATE INDEX&quot;); before proceeding. The comment explains <strong>why</strong>: otherwise an in-progress INSERT/UPDATE in <em>this same session</em> could have already picked its list of target indexes and would not update the new one. <a href="https://doxygen.postgresql.org/indexcmds_8c_source.html">doxygen.postgresql.org</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UMcNh69KJ13rd3smEGhPhA.png" /></figure><ul><li>CheckTableNotInUse() (in tablecmds.c) raises<br> ERROR: cannot %s &quot;%s&quot; because it is being used by active queries in this session<br> when the relation’s refcount shows it’s still in use by the current backend (or if there are pending AFTER triggers).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4yqsW0fbWuNUwNLAn6h_Pw.png" /></figure><p>It clearly says just above CheckTableNotInUsethat there’s an open cursor or active plan.</p><blockquote>“Disallow ALTER TABLE (and similar commands) when the current backend has any open reference to the target table besides the one just acquired by the calling command; this implies there’s an open cursor or active plan.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9-4vwUugwbONRcQhlCkcqA.png" /></figure><p>So not another session. <strong>This</strong> session. And if there’s no parallelism and no second plan lingering, what’s left? As Sherlock Holmes would say: once you eliminate the impossible, whatever remains, however improbable…. is that one open cursor someone forgot to close.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3EcQDwJLukU8CMALJJhgEA.jpeg" /></figure><p>I slapped a CLOSE ALL; at the top of the migration file just to test the hypothesis. Boom =&gt; green CI. Then I hunted down the culprit, a recently added explicit cursor loop (OPEN …; FETCH …;) instead of a tidy FOR r IN SELECT … LOOP.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4tJD8bB-A5n27SJAMWjXGg.jpeg" /><figcaption>Culprit Found</figcaption></figure><p>The cursor never got closed, so the relation stayed referenced, and Postgres (correctly) refused.</p><p><strong>In short: my session blocked….. my session. Peak self-sabotage.</strong></p><p><strong>Simple fix:</strong> stop leaking cursors. Prefer FOR rec IN SELECT … LOOP (implicit cursor) or explicitly CLOSE the cursor (also in EXCEPTION block).</p><p>PS : Slightly off topic but doxygen.postgresql.org is cool.<br>A piece of history : Magnus Hagander announcing auto-generated source code documentation (not the user manual).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*yNF5Wg_1Y6mmG5ZhEQ5nlg.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3978fd29245f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Slonik on the Catwalk: PGConf.EU 2025 Recap]]></title>
            <link>https://drunkdba.medium.com/slonik-on-the-catwalk-pgconf-eu-2025-recap-b4990c626271?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/b4990c626271</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[pgconf]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Mon, 27 Oct 2025 11:53:47 GMT</pubDate>
            <atom:updated>2025-10-27T12:36:28.233Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>I volunteered as a room host and Slonik guide.<br>Best gig: posing our elephant. The photographer had runway-level ideas. Slonik delivered every single time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lKT_xGfXAuhfCV5OEgwNeg.jpeg" /><figcaption>Slonik modelling session</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V968rMy_NK8cy4Zb4mrZrA.jpeg" /><figcaption>Slonik having a Diva moment</figcaption></figure><h3>Community Day ~ people &gt; hype</h3><ul><li><strong>PostgreSQL &amp; AI Summit</strong>: I sat on the panel and played “Team Human” vs Skynet (As advised by John Connor in the future).<br> <a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/7149-postgresql-ai-summit/">postgresql.eu</a></li><li><strong>“Establishing the PostgreSQL standard: What’s Postgres compatible?”</strong><br>Half-day workshop, lot of brain storming and discussion split into groups then presenting your group’s conclusion on what makes postgres derivatives compatible with community postgres. We spun up a Telegram group to keep building the rubric post-conference. <a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/7152-establishing-the-postgresql-standard-whats-postgres-compatible/">postgresql.eu</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xMLr01XRUo1SejbraVDA4g.jpeg" /><figcaption>The Hallway Track</figcaption></figure><h3>Coffee with CYBERTEC (meeting Laurenz Albe)</h3><ul><li>Picked the <strong>“Coffee with CYBERTEC”</strong> option to meet Laurenz Albe, the most prolific Stack Overflow answerer.</li><li>We traded notes on most popular <strong>features to adopt</strong> from other databases, their <strong>feasibility</strong>, and <strong>why Postgres avoided them historically</strong>.</li></ul><p>I left with a <strong>starting map for contributing to core.</strong></p><h3>Talks I caught (and why they stuck)</h3><p><strong>“Don’t do that!” — Laurenz Albe</strong><br>A rapid-fire list of Postgres anti-patterns. Simple, blunt, useful from the most beloved speaker of the conference. (<a href="https://www.postgresql.eu/events/pgconfeu2025/sessions/session/6838/slides/742/dont_do_that_m.pdf">postgresql.eu</a>)</p><p><strong>Parsing Postgres logs the non-pgBadger way — Kaarel Moppel</strong><br>Meet pgweasel. Lean CLI. Fast. Cloud-friendly. For prod support, less noise beats glossy graphs. I’m convinced. (<a href="https://www.postgresql.eu/events/pgconfeu2025/sessions/session/6975-parsing-postgres-logs-the-non-pgbadger-way/">postgresql.eu</a>)<br><a href="https://github.com/kmoppel/pgweasel">https://github.com/kmoppel/pgweasel</a></p><p><strong>Improved freezing in VACUUM — Melanie Plageman</strong><br>Cleaner anti-wraparound story. Scan all-visible (not all-frozen) pages early; fewer emergency freezes later. Sensible, much needed change. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/6952-improved-freezing-in-postgres-vacuum-from-idea-to-commit/">postgresql.eu</a>)</p><p><strong>Patroni + pgBackRest: better together — Stefan Fercot</strong><br>Power couple of Postgres, best HA tool with best Backup tool. Tight HA+DR integration. Bootstrap from backups, safe standby rebuilds, PITR under Patroni’s control. (<a href="https://www.postgresql.eu/events/pgconfeu2025/sessions/session/6961-patroni-and-pgbackrest-better-together/">postgresql.eu</a>)</p><p><strong>DBTune: AI-driven tuning</strong><br>Autonomous parameter tuning across self-hosted and managed Postgres. Looks mature enough for a lab trial. I’m tempted to test in QA. (<a href="https://www.postgresql.eu/events/pgconfeu2025/sessions/session/7187-dbtune-ai-driven-performance-tuning-for-all-postgresql-flavors/">postgresql.eu</a>)</p><p><strong>The SyncRep Detective Story</strong><br>Fascinating detective story and scientific approach to tracing root cause. Resonated with my past setup where commit_delay/commit_siblings helped on AWS networked storage. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/7037-the-syncrep-detective-story-chasing-ghosts-in-postgresql-finding-demons-in-storage/">postgresql.eu</a>)</p><p><strong>MultiXacts: usage, side-effects, monitoring — Divya Sharma</strong><br>Row-lock pileups and vacuum side effects, explained. We don’t hit them often in current company (rareSELECT … FOR UPDATE), but I left with better alarms to build. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/6887-multixacts-in-postgresql-usage-side-effects-and-monitoring/">postgresql.eu</a>)</p><p><strong>Fast-path locking in PG18 — Tomas Vondra</strong><br>Shines with many relations and partitions. We’re light on partitioning at current company, so the gains will be modest for us. Still, good progress. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/6891-fast-path-locking-improvements-in-pg18/">postgresql.eu</a>)</p><p><strong>Patroni: what the blog posts don’t tell you — Cameron Murdoch</strong><br>The “missing manual”: hardening, proxies, DCS choices, failsafe option and upgrades. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/7018-patroni-what-the-blog-posts-dont-tell-you/">postgresql.eu</a>)</p><p><strong>We have multiple concurrent versions of this title trying to understand MVCC (Boris Mejias)</strong><br>It’s hard to describe this talk cause you have to experience it live to fully appreciate the second best database comedian in the world.</p><p><strong>Tracking plan shapes over time — pg_stat_plans (Lukas Fittl)</strong><br>Plan IDs + pg_stat_plans let you watch plan drift over time. This will be gold for catching plan fluctuations. (<a href="https://www.postgresql.eu/events/pgconfeu2025/schedule/session/7112-tracking-plan-shapes-over-time-with-plan-ids-and-the-new-pg_stat_plans/">postgresql.eu</a>)<br><a href="https://github.com/pganalyze/pg_stat_plans">https://github.com/pganalyze/pg_stat_plans</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mMbHlV9p78pn-KyukvDIYg.jpeg" /><figcaption>Feeding Session</figcaption></figure><h3>Conference vibe</h3><p>Riga was friendly. Hallway track was lively. Slonik worked overtime and loved the camera. See you next year.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YK30PMnHe4VhLCJdQ5SKuQ.jpeg" /><figcaption>“My Watch Has Ended” — Slonik Snow</figcaption></figure><p>PS: If you are still suffering from Postgres conference hangover and crave more Postgres content then head over to Prague next month for Prague Postgres Meetup or in January for P2D2 conference.</p><p><a href="https://docs.google.com/presentation/d/1XwSOlMNcB7d3IH94CmQ6uOUkPmhVWeqE7KacBl2xF_Y/edit?usp=sharing"><strong><em>13 REASONS WHY YOU SHOULD ATTEND P2D2 PRAGUE?</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b4990c626271" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PGConf.EU 2025: The Underground Map for Database Nerds]]></title>
            <link>https://drunkdba.medium.com/pgconf-eu-2025-the-underground-map-for-database-nerds-da3587a90b2e?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/da3587a90b2e</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[postgresql]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Fri, 17 Oct 2025 22:57:58 GMT</pubDate>
            <atom:updated>2025-10-17T22:57:58.446Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>PGConf.EU schedule can feel like a parallel query gone wild, so many great talks but not enough CPU.<br>I built this guide to help my fellow database nerds skip the overwhelm and enjoy the best prod-DBA focussed sessions without a single deadlock.<br>Follow this path, and you’ll cruise through the conference like a perfectly tuned autovacuum.</p><h3>🗓️ Wednesday, Oct 22 — Warming Up the Buffers</h3><p><strong>11:15 – 12:05 in Omega 1 : </strong><em>Don’t Do That!</em> <br>Laurenz Albe reminds us that every bad Postgres habit comes with a sequel called “incident report.”</p><p><strong>13:05 – 13:35 in Omega 2 : </strong><em>Parsing Postgres Logs the Non-pgBadger Way</em> <br>Kaarel Moppel shows that pgweasel and caffeine can out-analyze any dashboard.</p><p><strong>13:45–14:35 in Alfa : </strong><em>Improved Freezing in Postgres Vacuum: From Idea to Commit</em> <br>Melanie Plageman walks us through the icy depths of tuple immortality.</p><p><strong>14:45–15:35 in Omega 2 : </strong><em>Operational Hazards of Running PostgreSQL Beyond 100 TB</em> <br>Teresa Lopes shares real stories and engineering lessons from scaling Postgres into the terabyte realm, where every decision costs you.</p><p><strong>16:05–16:55 in Omega 2 </strong>: <em>What You Should Know About Constraints (and What’s New in 18)</em> <br>Gülçin Yıldırım Jelínek explores how new enhancement to constraints in PG 18 make data integrity both smarter and more flexible.</p><p><strong>17:05–17:55 in Omega 1 : </strong><em>Hacking pgvector for Performance</em> <br>Daniel Krefl reveals clever hacks to push filtering and indexing deeper into pgvector for faster, leaner similarity searches.</p><h3>🧱 Thursday, October 23 — The Day of Observability and Enlightenment</h3><p><strong>09:25–10:15 in Omega 2 : </strong><em>Unified Observability: Monitoring Postgres Anywhere with OpenTelemetry</em> (Yogesh Jain)<br>Learn how to unify metrics, logs, and traces across cloud, containers, and bare-metal Postgres instances using OpenTelemetry to build scalable, vendor-agnostic observability.</p><p><strong>10:25–10:55 in Omega 1 : </strong><em>EXPLAIN: Make It Make Sense</em> (Aivars Kalvāns)<br>Find out how to turn cryptic EXPLAIN output into actionable insights, mapping planner nodes to real costs so you can tame rogue queries.</p><p><strong>11:25–12:15 in Alfa : </strong><em>The SyncRep Detective Story: Chasing Ghosts in PostgreSQL, Finding Demons in Storage</em> <br>Dmitry Fomin unravels a real performance mystery and exorcises the demons hiding deep inside the storage.</p><p><strong>13:55–14:45 in Alfa</strong> : <em>AIO in PG 18 and Beyond</em> (Andres Freund)<br>Explore how asynchronous I/O enhancements in Postgres 18 shift the performance landscape.</p><p><strong>14:55–15:45 in Omega 1 : </strong><em>Table Repacking, Done Right</em> (Álvaro Herrera &amp; Antonin Houska) <br>Learn how <strong>REPACK CONCURRENTLY</strong> (targeting Postgres 19) can deflate bloat without downtime, how it works under the hood, and how it might rescue frustrated DBAs from locking hell.</p><p><strong>15:55–16:25 in Omega 2</strong> : <em>All About Common Vulnerabilities and Exposures in PostgreSQL</em> (Priyanka Chatterjee)<br>Get real: dissect real CVEs in PostgreSQL, see how they were exploited, and learn how to protect your systems before headlines hit.</p><h3>🧨 Friday, October 24 — The Day of Failures, Recovery &amp; Redemption</h3><p><strong>09:25–10:15 in Omega 2</strong> : <em>PostgreSQL as a Graph Database: Who Grabbed a Beer Together?</em> (Taras Kloba)<br>Taras compares Apache AGE, pgRouting, and pgGraph in a live demo to show how PostgreSQL can moonlight as a graph database and map community connections (yes, including who met at the bar).</p><p><strong>10:25–10:55 in Omega 1 : </strong><em>Fast-Path Locking Improvements in PG18</em><br>Tomas Vondra takes us on a deep dive into lock manager refinements in PG 18 that reduce contention latency in hot, high-load scenarios.</p><p><strong>11:25–12:15 in Omega 1 : </strong><em>Patroni: What the Blog Posts Don’t Tell You…</em> (Cameron Murdoch)<br> Cameron pulls back the curtain on real Patroni deployments: split-brain, failover pitfalls, and the nitty-gritty never documented.</p><p><strong>13:15–13:45 in Omega 2</strong> : <em>Tracking Plan Shapes Over Time with Plan IDs &amp; the New pg_stat_plans</em> (Lukas Fittl)<br>Lukas unveils how plan ID versioning and the new pg_stat_plans help you track plan drift, regressions, and performance ghosts over time.</p><p><strong>13:55–14:45 in Alfa : </strong><em>We Have Multiple Concurrent Versions of This Title Trying to Understand MVCC</em> (Boriss Mejias)<br>Boriss leads you through concurrency, snapshot races, and how Postgres keeps isolation sane in the chaos of multiversions.</p><p><strong>14:55–15:45 in Omega 2 : </strong><em>Database in Distress: Testing and Repairing Different Types of Database Corruption</em> (Josef Machytka)<br>Forensic lab of data corruption cases and how to surgically repair them.</p><p><strong>16:15–17:00 in Omega 1 : </strong><em>Lightning Talks (Maybe you?)</em><br>A wild finale: short, sharp experiments, hacks, and stories to spark ideas and laugh off days of log parsing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eYEtdjD3m6fyVYp8med02w.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da3587a90b2e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unsung Heros of Postgres : Episode I]]></title>
            <link>https://drunkdba.medium.com/unsung-heros-of-postgres-episode-i-b9a7056447d2?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/b9a7056447d2</guid>
            <category><![CDATA[postgresql-database]]></category>
            <category><![CDATA[database-administration]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Sun, 14 Sep 2025 17:25:31 GMT</pubDate>
            <atom:updated>2025-09-14T17:25:31.442Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<h3>Unsung Heros of Postgres : Episode I</h3><p>Not all heroes wear capes. In PostgreSQL, some don’t even write code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fhn5NG4U11XEIDLO" /></figure><p>At <a href="https://pgday.at/talk/roll-up-your-sleeves-contributing-to-postgres-beyond-code/">PGDay Austria</a>, Floor Drees highlighted this truth: countless contributions to PostgreSQL happen outside of code commits and patches.</p><p>Floor introduced <strong>postgres-contrib.org</strong>, a website launched in July 2024 by members of the community. Its mission is simple but powerful, celebrate the people behind PostgreSQL. Advocates, conference organizers, volunteers, speakers, bloggers, sysadmins, the security team, the Code of Conduct committee, the funding group… the list goes on.</p><p>Curious, I asked if folks who tirelessly answer questions on PostgreSQL Slack and Telegram could also be recognized. Floor and Christoph Berg explained that measuring contributions on such fluid, fast-moving platforms is difficult. Still, Floor encouraged me to write about them and even to add my own blog to Planet PostgreSQL (Finally😄).</p><p>I’ve noticed a trend, more people are asking questions on Slack or Telegram than on the classic mailing lists. For those coming from other databases, pgsql-hackers can feel intimidating. By contrast, Slack and Telegram provide approachable, beginner-to-intermediate spaces where conversations flow naturally.</p><p>So, taking Floor’s suggestion to heart, here’s my first attempt at spotlighting a few unsung heroes.</p><p>This is only the beginning, many more names will follow.</p><h3>A. Postgres Slack</h3><h3>To join: <a href="https://pgtreats.info/slack-invite">https://pgtreats.info/slack-invite</a></h3><p>Slack is my go-to platform. Threads keep discussions tidy, and I spend most of my time there. These are some of the community members I see helping every day.</p><p><strong>Depesz</strong> — Spot the legendary orange hairs in your thread, and you know help has arrived. One of the most prolific and consistent experts on Postgres slack.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ta0b4eXEZo3uokt0-WWeuw.png" /></figure><p><strong>Jeremy Schneider</strong> — Jeremy answers both cloud and bare-metal questions, and you’ll also find him sharing wisdom in the Aurora channel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iu4O-4t9UYOLy4eGmjit0A.png" /></figure><p><strong>Ants Aasma</strong> — A performance problem? Ants has an answer. Every. Single. Time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AakIzTARC6kamKpzXVIarw.png" /></figure><h3>B. Postgres Telegram</h3><h3><a href="https://t.me/postgreschat">https://t.me/postgreschat</a></h3><p>I haven’t spent as much time here yet, but one name already shines through.</p><p><strong>Stefanie Janine Stölting</strong> — Admin of the group, and always ready with sharp, technical answers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/990/1*qoeKng8tm5hgoIfY1_2fIA.png" /></figure><p>This list is just the start. PostgreSQL thrives because of the people who show up, share knowledge, and support others. I’ll be adding more names in the next round.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b9a7056447d2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Making of “Postgres Is”]]></title>
            <link>https://drunkdba.medium.com/the-making-of-postgres-is-5034c0dc4639?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/5034c0dc4639</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Thu, 27 Feb 2025 01:00:35 GMT</pubDate>
            <atom:updated>2025-03-05T20:20:33.333Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/621/0*eefd4zokK2Ts3wC4.png" /></figure><h3>Philosophy behind “PG Scorecard”:</h3><p>Postgres is an open-source database boasting an impressive 30-year legacy and a potent network effect. Its vibrant community has nurtured enduring credibility and resilience.</p><p>Naturally, emerging database startups want to harness this “Network effect” by claiming Postgres compatibility. Yet, without intrinsic checks on such assertions, this risks spiraling out of control and enticing malevolent actors.</p><p><a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/blob/main/readme.md">The Postgres Compatibility Index</a> aims to create an open-source framework to validate these claims. My drive to introduce automated tests stems from the need to compare user experiences between the community edition and the more flamboyant, serverless, cloud-based, or specialized derivatives. Are users granted the same freedom, flexibility, and reliability they enjoy with the community version of PostgreSQL?<br>For example, Technically a cloud vendor can be compatible to Postgres however by not allowing freedom to use external programming language such as pl/perl,pl/python or C functions you would be denying users same experience as on self hosted community Postgresql.</p><p>For now, I’ve sidelined the obvious champions such as EDB Postgres, Azure FlexiServer, Amazon RDS, and Google CloudSQL. Time’s the culprit. By day, I’m a DBA; by weekend, a coder. They’ll join the fray when the clock permits.</p><p>There are lot of complex tests that I would like to have but not figured out yet how to incorporate them. If you wish to contribute tests or code, please submit a pull request.</p><p><strong>MIT Licenced code so feel free to contribute and improve it.</strong></p><p><strong>Contribut to scoring methodology code here</strong> ==&gt; <a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/blob/main/postgres-compatibility-index/pci_autotest.py"><strong>pci_autotest.py</strong></a></p><p>Are you a vendor itching to showcase your creation?</p><p>Run autotest.py against your database. Send a pull request with the JSON output, logs, and screenshots. Step into the spotlight.</p><p><strong>Need your favorite db featured on site</strong> ==&gt; <a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/tree/main/postgres-compatibility-index/outputs"><strong>Outputs</strong></a></p><p>Update: In response to a trademark notice from the PostgreSQL Community Association of Canada, domain has been changed from “Postgres.Is” to <a href="http://pgscorecard.com">pgscorecard.com</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5034c0dc4639" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Postgres Is]]></title>
            <link>https://drunkdba.medium.com/postgres-is-3cbae80c84a3?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/3cbae80c84a3</guid>
            <category><![CDATA[database]]></category>
            <category><![CDATA[dba]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[data]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Mon, 17 Feb 2025 04:10:57 GMT</pubDate>
            <atom:updated>2026-01-31T21:08:25.441Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>When Amazon unveiled DSQL, social media buzzed with viral discussions about its touted PostgreSQL compatibility.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*fvLsTNPXMqhuyaWbeQGeOw.png" /></figure><p>Some even joked that if DSQL truly is PostgreSQL compatible, why Larry Ellison has not proclaimed Oracle to be the world’s most PostgreSQL-compatible enterprise database?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/0*TMHIfgIS0kDqPSby" /><figcaption>Larry quoting Genghis Khan or otherway round?</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/913/1*FJu_ysfuhfBjOctxgHqcPg.png" /><figcaption>Everyone claiming they are Postgres, Circa 103-BC (colorized)</figcaption></figure><p>This notion lingered in my mind when I encountered Gunnar (the former lead at Debezium) and Tudor (CTO of Xata) in a discussion about standardizing what it truly means to be PostgreSQL-compatible. Inspired by their exchange, I went on to create the Postgres Compatibility Index.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BVnyi_jcKAaS01IK4qh5rA.png" /><figcaption>The birth of PCI</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*snQTYWjJO9Wh0iikaNtjgg.png" /><figcaption>One index to rule them all</figcaption></figure><h3>Postgres Compatibility Index (PCI)</h3><ul><li>PCI runs a battery of tests on the database in question, poking at every feature Postgres has to offer.</li><li>Each feature is scored, depending on whether it works, or implodes spectacularly.</li><li>The results are weighted, calculated, and distilled into a single PCI score, a percentage of compatibility perfection.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*4kX3-4g1I3MiEJN4tc2JmA.png" /><figcaption>PCI in Action</figcaption></figure><p>•The code for the PostgreSQL Compatibility Index (PCI) is freely available under the MIT License, because the journey to compatibility should be a collaborative effort.</p><p>•Feel free to explore the repository and send a PR to help enhance PCI for the entire Postgres community:<br> <a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/tree/main">PostgreSQL Compatibility Index on GitHub</a></p><h3>Next Level :</h3><p>Web app is built upon the dynamic JSON output produced by running <a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/blob/main/postgres-compatibility-index/pci_autotest.py"><strong>pci_autotest.py</strong></a></p><p>Visit =&gt; <a href="https://pgscorecard.com/">PG Scorecard</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EzWTW5NbH09D7Q7VpEHYqQ.jpeg" /></figure><p>You can compare various attributes of different postgres derivatives.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fB9oVdNrdzc-Ot-94-QN7Q.jpeg" /></figure><p>Or</p><p>You can see how postgres derivates fare for a specific attribute.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fBlVUclfuyQH-vSbpfEQCw.png" /></figure><blockquote>If you want your favorite postgres derivative to feature on website then just run <a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/blob/main/postgres-compatibility-index/pci_autotest.py"><strong>pci_autotest.py</strong></a> and send me json output generated or if you are cloud provider then give me your free tier account. <em>:-)</em> .</blockquote><h3><strong>POSTGRES IS</strong></h3><p>While the Postgres Compatibility Index meticulously addresses the technical facets of PostgreSQL, it also prompts a deeper, philosophical inquiry: What does it truly mean to be PostgreSQL? To explore this question, I draw upon Philip K. Dick’s “Human Is” as a metaphor, reflecting on the evolution of PostgreSQL over three transformative decades. Following series of memes eloquently conveys what a thousand words alone could not capture.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/621/1*i1FcY_d-GorsphlHHrOIhQ.png" /></figure><ol><li>AI?</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*ongD3Y2Afu4J2wMyzDKHjA.png" /></figure><p>2. GraphDB?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7n-lGQwb_nTYgFpBOIyvNw.png" /></figure><p>3. Event streaming engine?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lTdqN4Mi5s4mPRl9Wvfy4Q.png" /></figure><p>4. Timeseries database?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*B1EdfeESBCE3V1mLKJN8gQ.png" /></figure><p>5. Document database?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/978/1*zNFNLldRu-FMGKRE0GY3QA.png" /></figure><p>6. Geospatial analytics tool?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FHAj3eCFoLQu1RDuLCIRVw.png" /></figure><p>7. A Search engine?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PnPKxg1RQTPsqSV5QpmpWg.png" /></figure><p>8. Data-lake?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HlQdsq397qGr0YbUzcALCQ.png" /></figure><p>9. Data Ecosystem</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q0ROiaUZcKIztRt4QL9OJg.png" /></figure><p>10. A Working Class Hero</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*isOLXp4_azu5Rc45olwFrA.png" /></figure><p>11. Galactus?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JlstsEZGUSaaNYHT75keng.png" /></figure><p>12. Postgres Is</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/973/1*_K6UlTlxhEpjCQcR6W3sgw.png" /></figure><p><strong>Update: </strong>In response to a trademark notice from the PostgreSQL Community Association of Canada, domain has been changed from “Postgres.Is” to <a href="http://pgscorecard.com/">pgscorecard.com</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3cbae80c84a3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PostgreSQL Compatibility Index: The Fellowship of the Database]]></title>
            <link>https://drunkdba.medium.com/postgresql-compatibility-index-the-fellowship-of-the-database-4005f818f97c?source=rss-3319eaf2a6c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/4005f818f97c</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[dba]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Mayur (Do not drink & database)]]></dc:creator>
            <pubDate>Tue, 10 Dec 2024 02:03:25 GMT</pubDate>
            <atom:updated>2024-12-17T23:29:35.869Z</atom:updated>
            <cc:license>https://creativecommons.org/publicdomain/mark/1.0/</cc:license>
            <content:encoded><![CDATA[<p>In the mystical realm of databases, a new hero rises every few moons — a shiny, next-gen PostgreSQL derivative, boldly claiming to be “Postgres-compatible.” Like Frodo bearing the One Ring, these new contenders promise to carry us beyond the limits of vanilla Postgres into the promised lands of limitless scaling, AI integrations, and zero downtime magic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/1*skzOsMmYB4rptW1O0FBk4Q.jpeg" /></figure><p>But while we DBAs gaze at these marvels with starry-eyed wonder, QA teams hunker down in Helm’s Deep, bracing for the inevitable orc army of compatibility bugs. They’ve seen the promises before, and they know the truth: <strong>“compatible” is often just marketing speak for “we hope it mostly works.”</strong></p><p>DBAs love the idea of embracing the future. We get excited when a new database claims to support distributed transactions, vector embeddings, and geospatial analytics while still being Postgres at heart. Imagine the scalability! The performance boosts! The bragging rights in Slack!</p><p>But QA? QA sees a Mordor of testing cycles, long nights, and a hundred Jira tickets labeled <strong>“Regression: </strong>Foreign Key<strong> not supported.”</strong></p><h3>The One Index to Rule Them All</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*__S18I_R-f8iWeLo" /></figure><p>Enter the <strong>PostgreSQL Compatibility Index (PCI)</strong>: a tool to help both DBAs and QA teams navigate this epic saga. The PCI is like the Council of Elrond — everyone gets to know the facts, lay their cards on the table, and decide whether this new database is the Aragorn we need or just another Boromir, doomed to fail us at a critical moment.</p><p>Here’s how it works:</p><ul><li><strong>PCI runs a battery of tests</strong> on the database in question, poking at every feature Postgres has to offer.</li><li>Each feature is scored, depending on whether it works, or implodes spectacularly.</li><li>The results are weighted, calculated, and distilled into a single PCI score, a percentage of compatibility perfection.</li></ul><p>And just like Gandalf, PCI doesn’t pull punches. It will expose the Balrog-sized gaps in compatibility that marketing conveniently forgot to mention.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2GpeQShOeyFOp5NH" /><figcaption>PCI Autotest in action, failures were induced on purpose to check scoring.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/1*tGMRixSfXepuaZHb-1h_Kw.png" /><figcaption>Improved reporting shows category and feature failed along with PCI Score.</figcaption></figure><h3>For the Manual Wizards in the Realm of Compatibility</h3><p>Not every compatibility journey requires the magic of automated tests — sometimes, a manual spellbook does the trick. The PostgreSQL Compatibility Index (PCI) also allows you to calculate scores manually by crafting a JSON input file with a fixed set of characteristics as defined in pci_calculator.py.</p><p>For instance, here’s how the PCI score was conjured for databases like <strong>CockroachDB</strong>, <strong>Amazon DSQL</strong>, and <strong>Yugabyte</strong>, using manually filled JSON files.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*o7yKKHXP23cJFpkR" /></figure><p>Below is an example of the input json for Yugabyte.</p><pre>{<br>    &quot;data_types&quot;: {<br>        &quot;Primitive Types&quot;: &quot;full&quot;,<br>        &quot;Complex Types&quot;: &quot;partial&quot;,<br>        &quot;JSONB&quot;: &quot;full&quot;,<br>        &quot;Geospatial Types&quot;: &quot;partial&quot;,<br>        &quot;Custom Types&quot;: &quot;full&quot;,<br>        &quot;Full-Text Search&quot;: &quot;full&quot;,<br>        &quot;Vector&quot;: &quot;no&quot;<br>    },<br>    &quot;ddl_features&quot;: {<br>        &quot;Schemas&quot;: &quot;full&quot;,<br>        &quot;Sequences&quot;: &quot;full&quot;,<br>        &quot;Views&quot;: &quot;full&quot;,<br>        &quot;Materialized Views&quot;: &quot;full&quot;<br>    },<br>    &quot;sql_features&quot;: {<br>        &quot;CTEs&quot;: &quot;full&quot;,<br>        &quot;Upsert&quot;: &quot;full&quot;,<br>        &quot;Window Functions&quot;: &quot;full&quot;,<br>        &quot;Subqueries&quot;: &quot;full&quot;<br>    },<br>    &quot;procedural_features&quot;: {<br>        &quot;Stored Procedures&quot;: &quot;full&quot;,<br>        &quot;Functions&quot;: &quot;full&quot;,<br>        &quot;Triggers&quot;: &quot;full&quot;<br>    },<br>    &quot;transaction_features&quot;: {<br>        &quot;ACID Compliance&quot;: &quot;full&quot;,<br>        &quot;Isolation Levels&quot;: &quot;full&quot;,<br>        &quot;Nested Transactions&quot;: &quot;no&quot;,<br>        &quot;Row-Level Locking&quot;: &quot;full&quot;<br>    },<br>    &quot;extensions&quot;: {<br>        &quot;Extension Support&quot;: &quot;partial&quot;,<br>        &quot;Foreign Data Wrappers&quot;: &quot;partial&quot;,<br>        &quot;Custom Plugins&quot;: &quot;partial&quot;<br>    },<br>    &quot;performance&quot;: {<br>        &quot;Index Types&quot;: &quot;partial&quot;,<br>        &quot;Partitioning&quot;: &quot;full&quot;,<br>        &quot;Parallel Query Execution&quot;: &quot;no&quot;<br>    },<br>    &quot;constraints&quot;: {<br>        &quot;Foreign Key&quot;: &quot;full&quot;,<br>        &quot;Check&quot;: &quot;full&quot;,<br>        &quot;Not Null&quot;: &quot;full&quot;,<br>        &quot;Unique&quot;: &quot;full&quot;,<br>        &quot;Exclusion&quot;: &quot;no&quot;<br>    },<br>    &quot;security&quot;: {<br>        &quot;Role Management&quot;: &quot;full&quot;,<br>        &quot;GRANT/REVOKE Privileges&quot;: &quot;full&quot;,<br>        &quot;Row-Level Security&quot;: &quot;full&quot;<br>    },<br>    &quot;replication&quot;: {<br>        &quot;Streaming Replication&quot;: &quot;full&quot;,<br>        &quot;Logical Replication&quot;: &quot;full&quot;<br>    },<br>    &quot;notifications&quot;: {<br>        &quot;LISTEN/NOTIFY&quot;: &quot;no&quot;,<br>        &quot;Event Triggers&quot;: &quot;no&quot;<br>    },<br>    &quot;miscellaneous&quot;: {<br>        &quot;Temporary Tables&quot;: &quot;full&quot;,<br>        &quot;Monitoring and Statistics&quot;: &quot;full&quot;<br>    },<br>    &quot;utilities&quot;: {<br>        &quot;pg_dump&quot;: &quot;full&quot;,<br>        &quot;pg_stat_statements&quot;: &quot;full&quot;,<br>        &quot;pg_walinspect&quot;: &quot;no&quot;,<br>        &quot;amcheck&quot;: &quot;full&quot;<br>    },<br>    &quot;penalty&quot;: {<br>        &quot;superuser_restricted&quot;: &quot;no&quot;,<br>        &quot;transaction_limits&quot;: &quot;no&quot;,<br>        &quot;read_limits&quot;: &quot;no&quot;<br>    }<br>}</pre><p><strong>Why the manual mode? </strong>Because automating tests for every single characteristic using only SQL/PLpgSQL can feel like forging the One Ring — it’s a monumental task, especially when new-gen databases uses different nomenclatures or semantics for core features. For these situations, manual mode is your trusty sword and shield.</p><p>So the next time a database vendor claims “Postgres compatibility,” don’t just trust the marketing pitch. Run PCI, check the score, and then decide whether you’re leading your team to Gondor — or straight into Mordor.</p><h3>Join the Quest: Open Source Awaits!</h3><p>The code for the PostgreSQL Compatibility Index (PCI) is freely available under the MIT License, because the journey to compatibility should be a collaborative effort. Whether you’re inspired to add new features, improve existing ones, or simply sharpen the edges of the tool, your contributions are welcome!</p><p>Feel free to explore the repository and send a PR to help enhance PCI for the entire Postgres community:<br><a href="https://github.com/secp256k1-sha256/postgres-compatibility-index/tree/main/postgres-compatibility-index">PostgreSQL Compatibility Index on GitHub</a></p><p><em>May your queries be efficient, your indexes be optimized, and your compatibility claims… actually compatible.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4005f818f97c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>