← All digests

DBMS Weekly — 2026-10-12 (week of Oct 12–18)

PostgreSQL 19 RC1 shipped on 15 October, and the bug reports kept coming. The most serious this week is not new in 19: CLUSTER and REPACK silently drop a row that the same transaction inserted and then updated inside a rolled-back savepoint, on every branch from 14 to master. Two more wrong-results bugs in released branches came in: a chain of LEFT JOINs since 16, and a hashed SubPlan reused after a rescan. Last week's antijoin bug is fixed. The release now has an upgrade problem: three 19 commits stopped consulting LC_CTYPE, so text-search and pg_trgm indexes built by 18 miss rows after pg_upgrade in ICU and builtin-collation databases. A libpq option that let any dblink user pin a backend in an unkillable loop was reverted after RC1. PgBouncer 1.26.1 fixes a SCRAM authentication bypass. On the blogs, Materialize replaced SERIALIZABLE with a READ COMMITTED design it proved linearizable in Lean, after SIRead locks collapsed its metadata store at about 4,300 ops/s. Repeated EXPLAIN ANALYZE timings turn out to depend on synchronize_seqscans. And the CommitFest grew by a net +31, the largest gain of any fully counted week so far.

PostgreSQL

  • PostgreSQL 19 RC1 released — out on 15 October as planned. The announcement confirms RC2 on 12 November, the same day as the minor releases, which "will include a large number of fixes", and GA on 19 November. The libpq servicefile revert (see the mailing lists below) landed after RC1 was stamped, so RC2 will already differ from it visibly. (PostgreSQL Global Development Group · pgsql-announce) Changes since Beta 4:
    • fixes to REPACK (CONCURRENTLY), pg_plan_advice, the new planner optimisations that depend on whether an expression can be NULL, automatic logical decoding at wal_level=replica, and parallel autovacuum
    • postgres_fdw statistics import now runs as the foreign table's owner, not as the user running ANALYZE
    • COPY (query) TO … (FORMAT json) now uses the query's column names
  • Building a linearizable log on READ COMMITTED isolation — Materialize keeps its storage metadata in a small, hot Postgres table used as a compare-and-set log. In June a self-managed deployment hit a metastable failure under SERIALIZABLE. A short slowdown let SIRead locks pile up into the hundreds of thousands, which made every insert's conflict check slower, and latency went from milliseconds to 30 s and stayed there until load was removed. On a db.r6g.2xlarge RDS reproduction, throughput collapsed above about 4,300 CaS/s. The redesign runs every operation as a single READ COMMITTED statement and rests on one invariant: a shard's sequence numbers are always contiguous. Then "the predecessor exists and the PK rejects its successor" means "expected is the head". FOR KEY SHARE on the predecessor orders appends against truncating DELETEs, and a never-truncated marker row fences stale first writers, because NOT EXISTS reads the snapshot while the PK check sees the live index. They modelled Postgres READ COMMITTED in Lean 4 and proved the design linearizable, including the mixed-version rollout. The same benchmark then reached about 13,000 CaS/s without collapsing; they ran out of load first. (Petros Angelatos · materialize.com) [vendor blog — substantive]
  • EXPLAIN ANALYZE is a sample size of one — SELECT id FROM events WHERE tenant_id = 42 LIMIT 20 on a 1.5M-row, 31,915-page table ran once in 77.97 ms and nine times in about 0.07 ms, with every buffer a shared hit each time. The cause is synchronize_seqscans. For a table larger than a quarter of shared_buffers, a new seqscan starts where the previous one last reported its position (reported every 16 pages), so every later run started just before this tenant's rows at the end of the heap. With the setting off, every run took 80.8 ms (stddev 1.3%). The same statement also returned different rows with nothing writing. His rule for reading repeated runs: a stddev/mean near √N means one run was different; around 0.6 and rising means state is accumulating. (Alexander Ioffe · exobench.ai)
  • Zero-downtime Postgres upgrades with logical replication — part 3 of the series, reproducible with docker-compose on 14.24, 16.15, 17.11, 18.6 and 19beta4 under about 50 commits/s of live traffic. (Dimitri Fontaine · tapoueh.org) What it measures:
    • cutover: writes stall for 181 ms (freeze with default_transaction_read_only, wait for a marker row, setval from pg_sequences, switch); rolling back over a live reverse subscription took 179 ms
    • pg_upgrade --link: time follows object count, not data size — 1.69 s for 1,000 rows, 1.64 s for 5M rows/591 MB, 6.47 s for 5,000 near-empty tables
    • slots across pg_upgrade: since 17 they carry over, but a publisher's slot is kept only if it has consumed all WAL
    • PG19 WAIT FOR LSN on a logical subscriber doesn't work: the standby modes fail with "recovery is not in progress", primary_flush gives a false positive, and latest_end_lsn advances on receipt, not apply; use pg_replication_origin_status.remote_lsn plus a marker row
    • PG19 sequence replication moves values only on demand (still stale 20 s after a change); splitting sequences by residue, even on one side and odd on the other, removes the setval race
    • pglogical's apply worker crashed in his run when partitioned parents were targets
  • What gets TOASTed in Postgres — a reproducible psql walk-through, prompted by the LZ4 TOAST default. TOAST starts once a row passes 2,032 bytes and works on the largest values first. Window size matters: on a 210 KB string drawn from 5,000 words, pglz (4 KB window) fails its 25%-savings test and stores the value raw, while LZ4 (64 KB window) saves 15%. On repetitive JSON pglz compresses better (19 MB vs 24 MB, from 103 MB) but LZ4 loads 1.5–3× faster. The non-obvious part is partial reads: left(body,200) over 100 × 1 MB values needs 301 page lookups and about 1 ms with pglz, but 6,234 lookups and about 16 ms with LZ4, which detoasts the whole value. A 200-byte read at offset 500,000 of a bytea: 0.6 ms with EXTERNAL, 43 ms with LZ4, 116 ms with pglz. (Ahmed Darwich · planetscale.com) [vendor blog — substantive]
  • stack depth limit exceeded: four causes and Rails, ActiveRecord and RLS, measured — both on PG 17.11. (Chris van Eijk · now-next.nl)
    • a policy that reads its own table inline is caught at plan time as "infinite recursion detected"; the same subquery inside a function isn't, and recurses until the stack runs out (1,816 levels for SQL, 788 for PL/pgSQL). A SECURITY DEFINER helper owned by the table owner doesn't break the loop under FORCE; only a definer the policy doesn't apply to does
    • raising max_stack_depth from 2 to 7 MB lets runaway recursion go about 3.5× deeper, so it only fixes deep-but-finite cases: 1+1+… fails at 4,093 terms, as do 4,093 chained views; nested ORs hit "memory exhausted" at 3,331 terms, while 300,000 flat ORs and a 1M-value IN list are fine
    • ActiveRecord sends nothing when a connection returns to the pool: a request that set no tenant saw the previous tenant's rows 200 times out of 200, and with with_connection 155–160 of 600 requests got the wrong tenant
  • Old tech is sometimes better: a case study — tests a now-next claim that logging only changed columns makes audit triggers smaller but slower. 100k-row bulk UPDATE, best of 3: no trigger 238 ms; jsonb full row 921 ms / 42 MB; jsonb diff via jsonb_each 1,430 ms / 15.8 MB; hstore full row 830 ms / 39.8 MB; hstore diff (hstore(OLD) - hstore(NEW)) 798 ms / 14.7 MB. With hstore subtraction the diff is both the smallest and the fastest. (Hubert 'depesz' Lubaczewski · depesz.com)
  • Finding (and fixing) a silent throughput ceiling in PostgreSQL — HammerDB TPROC-C on PG18, 50 warehouses: going from 64 to 128 virtual users dropped NOPM from about 400k to about 52k with CPU at 35%. More than 75 backends queued on ExclusiveLock on extension of relation, the longest for 6.7 s; more vCPU and faster NVMe changed nothing. Hash-partitioning the hot table 10 ways cut Lock:extend waits by 98% and gave 7.2× the throughput. (Vishal Sawale · enterprisedb.com) [vendor blog] [unverified: hardware not disclosed; doesn't discuss PG16's multi-block relation extension]
  • Making COUNTs and the rest of search really fast (Part II) — ParadeDB's next reply to PlanetScale's TIN (10-05 issue), this time with mechanisms. Visibility checks were 81% of the page accesses in a COUNT; partitioning LSM segments by ctid gives each one a heap-page range, and a segment whose whole range is all-visible skips per-row checks (1,382 → 30 page accesses). A heap-page → first-DocId map replaces a stored ctid per document (after 1,000 updates, about 7,500 → under 400 buffer accesses), and terms in more than 10% of documents switch to bitmap postings, halving p99. Claims 2.0× TIN on Wikipedia COUNT and 10–22× on filtered and time-sorted queries TIN's benchmarks don't cover, while conceding no vendor benchmark settles "fastest". (Ming Ying · paradedb.com) [vendor blog — substantive] [unverified: vendor-run benchmark]
  • pg_vectorsearch — Tiger Data's new vector-index extension, alpha, PG18+; Postgres Weekly reports pgvectorscale moving to maintenance mode. (Tiger Data · github.com/timescale) [unverified: vendor performance claims]
    • PRISM, an IVF-style index with a hierarchical centroid tree kept in shared buffers; posting lists are RaBitQ-quantized with error bounds, so candidates are ruled out before reranking against full vectors in the heap; async I/O, AVX2/AVX-512/NEON
    • indexes existing pgvector vector/halfvec columns through binary-compatible types; lists never split on their own (prism_rebalance or REINDEX)
    • README warning: vectors over about 2 kB get TOASTed and the rerank pays a fetch the planner doesn't cost — use STORAGE PLAIN
    • on HN (210 pts, 53 comments) the authors said they left pgvectorscale's DiskANN-style graph because on low-dimensional data parts of it became unreachable and recall dropped silently; users found a 1,968-dimension cap and post-index filtering only
  • Open-source Citus matches Neki at 10M QPS on half the data nodes — follows last week's query-routers post. Read-only pgbench point SELECTs (80% on a hot 5% of keys), PG 18.4 + Citus 14.1 on r8gd.16xlarge: 24 workers with 48 routers did 10.03M tps (87.7% scaling efficiency from 1.43M on 3) at p50 1.06 ms, p99 11 ms. The post lists its own caveats: local NVMe vs EBS, 300 s runs, no writes, harness not yet published. (Álvaro Hernández · stackgres.io) [vendor blog] [unverified: vendor benchmark]
  • Declarative Schemas 2.0 with pg-delta — a new open-source schema-diff engine (alpha) replacing migra. It diffs two throwaway databases through the system catalogs and orders the DDL with a dependency graph built from them; objects owned by an extension (pg_partman partitions, pgmq queues) are changed through that extension's API, and --strict-coverage turns unsupported objects into CI failures. (supabase.com) [vendor blog]
  • pg_lake 3.5: Iceberg REST catalogs beyond Polaris — (Richie Bachala · snowflake.com)
    • configurable REST base URI, so Lakekeeper and Nessie work, with catalog-vended storage credentials; writes are still Polaris-only
    • breaking: rest_endpoint must now include the mount path (/api/catalog for Polaris)
  • PgBouncer 1.26.1 — security release, upgrade now. (PgBouncer · pgsql-announce)
    • CVE-2026-107350: a client that knows one SCRAM user's password can log in as any other SCRAM user, admins and backend superusers included, by sending a second StartupMessage during SCRAM auth against a nonexistent database
    • CVE-2026-107349 and -107348: infinite loops reachable by unauthenticated clients (an empty option name with ignore_startup_parameters set; an integer overflow with max_packet_size above default)
    • ignore_startup_parameters = search_path works again, as in 1.25
  • pgBackRest 2.60.0 — read before upgrading. (pgBackRest · pgsql-announce)
    • restore now stops with an error on any invalid page checksum, leaving the cluster incomplete; expire refuses to run if the oldest retained backup has checksum errors; checksum-page-error=n restores the warn-only behaviour
    • prefetching of multi-file and range reads from object stores; GCS Workload Identity Federation; OpenSSL 4
  • psqlODBC 18.00.0005 — CVE-2026-109448: the bound-parameter count was a signed 16-bit field, so binding more than 32,767 parameters wrote zeros past the binding array, in every version since 08.01.0102. An app that builds IN (?, ?, …) from user input can be pushed into it; the workaround is = ANY(?). (psqlODBC · pgsql-announce)
  • pg_hint_plan 1.9.0 — PG19 support, including 19's path generation strategies; the last release for 14. (pg_hint_plan · pgsql-announce)
    • fixes an infinite loop in the hint parser on multi-query strings, a crash when HintStateDump errors out, and a query ID not restored after SPI in hint-table lookup; hypothetical indexes are now ignored
  • credcheck 6.0 — password-policy extension; needs a server restart. (HexaCluster · pgsql-announce)
    • fixes a privilege escalation through a role's own ALTER ROLE when password_valid_until is set, plus a heap overflow
    • max_auth_failure and first-login password change now work through PgBouncer

PostgreSQL mailing lists

  • [hackers] [PG19] Indexes from 18 miss rows after pg_upgrade — three 19 commits stopped using LC_CTYPE (e113f9c102b for to_tsvector and pg_trgm, e39ece0343f for dmetaphone, b96a9fd76f3 for soundex/metaphone). In ICU and builtin databases with LC_CTYPE=C, text-search and pg_trgm indexes built by 18 miss rows after pg_upgrade; one accent or curly quote is enough (to_tsvector('simple','foo—bar don't naïve') gives 3 lexemes on 18.6 and 5 on 19rc1). The patch makes pg_upgrade --check warn and write a reindex_locale.sql; Jeff Davis asks whether a release note is enough "or does it demand something more". A companion thread lists more upgrade surprises missing from the notes. (Shihao Zhong; Jeff Davis, Tom Lane · pgsql-hackers) [patch posted]
    • io_workers was removed, so an 18 postgresql.conf that sets it stops 19 from starting
    • with LZ4 TOAST compression as default, long text keys can exceed the btree limit: restoring an 18 dump fails at ADD PRIMARY KEY and leaves the table without its key
    • English and German Snowball stems changed, so stored tsvectors stop matching; pg_lsn output is now zero-padded
  • [bugs] BUG #19760: CLUSTER loses a row inserted and then updated in a rolled-back subtransaction — silent data loss on 14 through master, REPACK included: BEGIN; INSERT …; SAVEPOINT s1; UPDATE …; ROLLBACK TO s1; CLUSTER t USING i; COMMIT leaves 0 rows. CLUSTER VERBOSE reports −1 recently-dead tuples, and any SELECT before CLUSTER sets hint bits and hides the bug. Suspected cause: HeapTupleSatisfiesVacuumHorizon() lacks the HEAP_XMAX_INVALID hint, so the rewrite defers the live original and then discards it with the aborted successor. Found by a query fuzzer. (Alperen Keles; Takeshi Ideriha, Ayush Tiwari · pgsql-bugs) [open]
  • [hackers] Revert libpq servicefile connection option in v19 — from pgsql-security: libpq loops forever on servicefile=/dev/zero, and postgres_fdw and dblink pass servicefile through for non-superusers. dblink's connect functions are executable by PUBLIC, so any user in a database with dblink could pin a backend in a loop that ignores statement_timeout, cancel and terminate; only SIGKILL, and therefore crash recovery, clears it. 18 and earlier are not exposed. Reverted on 19 and master on 18 October, after RC1; PGSERVICEFILE stays. (Sehrope Sarkuni; Michael Paquier · pgsql-hackers) [committed]
  • [bugs] BUG #19765: wrong result from a chain of LEFT JOINs and a hashed SubPlan reusing a stale hash table — two more wrong-results bugs in released branches. (Viktor Leis, Samuel Olaoye; Richard Guo, Tender Wang, Alexandra Wang · pgsql-bugs) [patch posted]
    • four VALUES lists left-joined with a WHERE on the first: all three join conditions vanish from EXPLAIN, on 16.0 through master (14 and 15 are correct). Guo: when an outer join commutes into a lower one's RHS its relid is added late, so constant propagation replaces a cloned qual with TRUE
    • an access-check EXISTS returns false where the answer is true, on 13 through 19, and OFFSET 0 fixes it: once OR-qual extraction references the hashed SubPlan twice, the hash table isn't rebuilt on rescan
  • [committers] Give antijoins made from sublinks a relid — last week's antijoin wrong-results bug (16+) is fixed, part of a run of planner and executor fixes. (Richard Guo, Tom Lane, David Rowley · pgsql-committers) [committed]
    • self-join elimination (18+) merged t with ONLY t, trusted a parent's unique index across its children, and ignored operator and collation when matching restrictions
    • EPQ run-time pruning (18+) used the parent's PARAM_EXEC values, so an UPDATE with a correlated subquery on a partitioned table could silently skip the row
    • Parallel TID Range Scan rescans reused the first range (19); a join-removal restart left stale state (16+)
  • [committers] Reorderbuffer: handle catalog-change-bearing aborted subxacts better — a logical-decoding bug as old as logical decoding. A catalog tuple written by an aborted subtransaction stayed in the top transaction's TUPLECID list; once pruning freed that line pointer and a later catalog insert reused the TID, historic snapshots could answer visibility wrongly — an assertion failure, or possibly wrong decoded output such as wrong column mappings. It surfaced only because the FOR PORTION OF revert shifted pg_attribute's page layout and broke test_decoding on two buildfarm animals. Back-patched to 14. (Bingshuai Li, Hayato Kuroda, Zhijie Hou; Álvaro Herrera · pgsql-committers) [committed]
  • [committers] Fix checks for aborted updating transaction in multixids — two places called TransactionIdDidAbort() without first checking TransactionIdIsInProgress(). In DoesMultiXactIdConflict(), an updater mid-abort could make a concurrent UPDATE fail with "new multixact has more than one updating member" (hit under TPC-C on 18.1 and 18.4); in heap_update(), a crashed updater inside a multixact still locked by others was treated as committed. All supported branches. (Chee Wooson; Heikki Linnakangas · pgsql-committers) [committed]
  • [hackers] [PG19] Promotion hangs behind a backend blocked on a stuck client — since 67c20979ce7 promotion waits for every process to absorb a ProcSignalBarrier, even at wal_level=replica with no slots. A backend blocked in secure_write() toward a client that stopped reading never does, so promotion took 300 s and more (up to about 16 minutes until TCP gives up), against 0.1 s on 18.6. Fujii's fix for 19 (df1be4ddc8) skips the barrier where it isn't needed; letting backends absorb barriers while blocked on client I/O stays master-only, because Sawada worried about running callbacks mid-protocol-message. (Shihao Zhong; Fujii Masao, Masahiko Sawada · pgsql-hackers) [committed] (19)
  • [bugs] BUG #19759: hashed SetOp / RecursiveUnion pre-allocate up to 64 GB — a 19 regression from 8f29467c57f: BuildTupleHashTable() no longer caps the initial bucket array at hash_mem, so a recursive UNION asks for 68,719,476,736 bytes in ExecInit before reading a row. David Rowley: "I think we're dreaming if we think we can avoid capping planner estimates in the executor"; his patch restores the cap. (Alperen Keles; David Rowley · pgsql-bugs) [patch posted]
  • [bugs] BUG #19756: ALTER COLUMN TYPE USING gives wrong values on partitions — silent wrong data on 13 through master, for partitions or inheritance children whose column numbers differ from the parent's (e.g. after a dropped column) when USING contains IS [NOT] NULL, IS TRUE/FALSE/UNKNOWN or a named argument: transformExpr has already rewritten those nodes in place with the parent's attnos. (kalakala; Sebastian Webber · pgsql-bugs) [patch posted]
  • [hackers] serializable anomaly – duplicate primary keys and SSI: a serializability violation — two SERIALIZABLE holes from the summer, both now with back-patchable fixes. In one, a concurrent DELETE through a secondary index lets a transaction see two rows with the same key and commit (through the PK index it raises a serialization failure). In the other, once a reader is summarized under load, CheckTargetForConflictsIn() reads a finishedBefore that OldCommittedSxact never sets, so the cycle is missed. (Jacob Brazeal, Vaijayanti Bharadwaj; Aleksander Alekseev, Andrey Borodin · pgsql-hackers) [patch posted]
  • [hackers] [PG19] Bugs found comparing 19 with 18 — last week's LLM-assisted sweep is now a triaged list, each item reproduced on 19rc1 against 18.6. Fixed: the promotion hang, jsonb_object_agg as a window function returning stale values, btree_gin missing rows in the repeated DST hour, pg_upgrade losing the newest multixid at offset wraparound. Still open: eager aggregation runs a volatile join clause once per group, a cancelled NOTIFY read that leaves the queue stuck, and JSON_ARRAY/JSON_OBJECT over a ROW marked immutable. (Shihao Zhong; Tom Lane, Fujii Masao · pgsql-hackers) [committed] in part
  • Follow-ups from last week — (pgsql-hackers/-bugs/-committers)
    • hash index: the second bug, a buffer-pin leak in _hash_finish_split's failure paths, is fixed back to 14 [committed]
    • GIN jsonpath: both wrong-results bugs are fixed back to 14; Fujii Masao found a third (j @@ '($ == 1).size().boolean()' returns nothing through the index) [patch posted]
    • NOT NULL simplification: Guo's v2 fixes every ON CONFLICT failure in a 15-type differential sweep but one; separately, Herrera found a partition can define a different virtual generated column expression and read NULL from a NOT NULL column, on 18 too [patch posted]
    • standby PANIC after VM truncation (18.6/17.11): Melanie Plageman prefers the original XLogTruncateRelation() fix; v5 adds a test, not committed yet [patch posted]
  • [hackers] Add Dockerfile for OSS Scanner — the plan is to enroll security@postgresql.org in an opt-in AI vulnerability-scanning programme for open-source projects, which needs a Dockerfile to build PostgreSQL; v2 reuses the CI container, as Andres Freund suggested. The scanner's seccomp blocks io_uring, so those AIO tests fail in it, but io_uring stays in the build so its code gets analysed. (Noah Misch; Andres Freund · pgsql-hackers) [patch posted]

CommitFest (open: PG20-3, #62)

  • Balance (Oct 12–18): 46 new · 15 closed (14 committed / 1 withdrawn, a duplicate) → net +31. (vs +20 last week, 11 higher. Both weeks are complete counts: new entries from sequential patch IDs #7434–#7479, closures from the history of every patch in #61 and #62.) 11 entries moved to Ready for Committer. Queue at scan: 366 needs review · 43 waiting on author · 102 ready for committer (511 active, up from 469). Three filers produced 14 of the 46 new entries: six [PG19] bug entries, four ruleutils deparse fixes, and four WITHOUT OVERLAPS fixes.
  • New this week: Specialize ExecIndexOnlyScan() like ExecSeqScan() (Matthias Dötsch) — Index Scan, Index-Only Scan and Bitmap Heap Scan still go through the generic out-of-line ExecScan(), so every tuple pays an indirect call plus runtime EPQ, qual and projection checks that SeqScan dropped in fb9f95502. The patch adds five Index-Only Scan variants chosen once at init, with IndexOnlyNext() forced inline. On a 5M-row all-visible table callgrind shows 4.8–6.3% fewer instructions (5.0–6.5% with LTO); wall-clock gains swing with -falign-functions=64, which a second reviewer reproduced. Asked whether LTO/PGO makes this unnecessary, Andres Freund said no: the compiler can't know es_epq_active, qual and projection are fixed for the query (thread). Also new: ZSTD TOAST compression and an extensible compression-method encoding (#7471, v8 of an older thread), Show "Table Block Fetches" in EXPLAIN ANALYZE for index-only scans (#7467, Peter Geoghegan), Improve ndistinct estimates for flattened UNION (#7462), Avoid O(N^3) planning time in choose_plan_name() (#7454), Bulk-write buffer access strategy for TOAST inserts (#7470), Hash table for the regexp cache (#7439), SELECT * EXCLUDE (…) (#7437). Last week's Batch TIDBitmap insertions in index scans (#7422) is already Ready for Committer.
  • Closed: committed: Fix stale tuplecid records left by aborted subtransactions (#7137), Fix two GIN JSONPath bugs (#7433), pgstat: a stats kind can use its own dsa/dshash (#7145), Clear walsender reader pointers after cleanup (#7431), Modernize XML parsing in CONTENT mode (#7032), Detect truncated zstd/gzip/lz4-compressed backups (#7129), Memoize shows only the last execution's stats for parallel workers (#7444, filed and committed the same week), REPACK: warn about skipping foreign partitions (#7240), and 6 smaller ones. Withdrawn: a duplicate entry (#7435).

Community pulse

  • Postgres isn't slow, your storage is — a resurfaced talk recap arguing for local NVMe under Postgres drew the week's biggest database thread. Practitioners posted numbers: moving RDS from r8g to r8gd (local NVMe) cut average I/O latency from about 1.0 ms to 0.1 ms; another team went from gp3 to io2 without buying extra IOPS and the system "calmed down". The case for network storage: a VM on local disk dies with its host, while an EBS volume can move and grow. Where it landed: local NVMe plus Postgres replication is faster and simpler for most workloads, as long as someone owns failover and node replacement — and a popular counter-thread said the real culprit is usually schema and queries. (Hacker News · 180 pts, 187 comments)
  • Postgres 19 delayed after AI reviewers find more bugs than humans can fix — The Register's write-up of last week's revert story took it to a general audience. The argument was whether LLM review creates work or only surfaces bugs already there; the better-received replies said the latter, since most of the bugs would also be in 18. One developer blamed a test suite made mostly of per-feature regression tests and said AI-scaled simulation testing and coverage-guided fuzzing had found him about 50 core bugs. On Lobsters (65 pts, 13 comments, on Peter Eisentraut's post) the "not vibe coding" line met open scepticism; the reply was that LLM review is not LLM-written code. (Hacker News · 219 pts, 93 comments)
  • Kubernetes is a terrible tool for most organizations — a DBA's war story: a 40-person incident call blamed the database while it sat 99% idle and the app's connections stayed idle in transaction for minutes. The top replies wouldn't blame Kubernetes — an unfinished transaction is an application bug, so set idle_in_transaction_session_timeout and fix the code — but did blame it for two things: a proxy's idle-TCP timeout silently killing long-lived connections, and CPU-throttled pods that stop responding with transactions open. The AI-generated advice posted during the call suggested indexes on views. (r/Database · 290 pts, 109 comments)

Wider DBMS & distributed data

  • Chasing that 32 ms tail latency in ClickHouse — after 2 s idle, Linux resets cwnd to initcwnd (8 MSS here). With TCP_NODELAY, the Native protocol's separate ProfileEvents/Log/Progress writes overflowed that window, so the end-of-stream packet waited an extra RTT. Batching the non-urgent metadata packets into one write halved server PSH segments (50 → 25) and took the tail from 32 ms to about 1 ms, server-side only, since customers often can't change tcp_slow_start_after_idle. Reproduced with netns + netem. Relevant to any wire protocol that flushes many small messages per query. (Kavi Kanagaraj · clickhouse.com) [vendor blog — substantive]
  • SurrealKV 1.0 replaces RocksDB in SurrealDB — a Rust LSM engine with snapshot isolation. (Tobie Morgan Hitchcock · surrealdb.com) [vendor blog — substantive] [unverified: single-run vendor benchmark, non-default SurrealKV settings]
    • adaptive-radix-tree memtable in a fixed arena, where RocksDB and Pebble use skiplists
    • a "commit ring": committers validate in parallel, then one flusher orders a group and appends the WAL with at most one fsync
    • differential testing against an in-memory model, 2.5M ops per CI run
    • with sync durability vs RocksDB: point reads 7.95×, updates 6.10×; without sync, RocksDB writes 1.9–2.4× faster, and peak memory is 1.79 vs 1.02 GiB
  • YSQL Connection Manager is GA — a transaction-mode pooler built into each node of a Postgres-derived engine. Instead of the pooler parsing SQL, the query layer reports every session-state change — SETs inside functions, SETs undone by rollback, ALTER ROLE/DATABASE … SET — and that state is replayed on whichever backend runs the next transaction. LISTEN, temp tables, WITH HOLD cursors, SQL PREPARE and SET ROLE still pin the session. Compare last week's CF #7415 (extensible ReadyForQuery for poolers). (Suranjan Kumar · yugabyte.com) [vendor blog — substantive] [unverified: vendor numbers]
  • Testing DuckDB 2.0 on our Iceberg datasets — TPC-H SF10 on Iceberg, 2.0 preview vs 1.5.6. (Javier de la Torre · lakehousebox.com)
    • same data centre, cold: 105.9 → 62.7 s (1.93× per-query geomean), the same ~12 GB read over 52% more GETs
    • over home fibre: 1.04×, with some queries pulling 2–3× the bytes from over-eager prefetch
    • warm runs regress: 1.5.6 re-reads nothing, 2.0 re-fetches 170 MB, and q09/q21 are slower even with zero network
    • Iceberg writes go from 409 files of ~5 MB to 4 of ~536 MB, which explains part of the read gain
  • Why sorted Parquet files don't guarantee an ordered scan in DataFusion — traced through DataFusion 55.1.0: a scan partition concatenates its files instead of merging them, so declared order (WITH ORDER, or sorting_columns read only from the first row group) survives only if each file's max ≤ the next file's min. Overlapping ranges silently drop the ordering and the GROUP BY falls back to hashing; neither declaration nor metadata is verified, so a wrong one gives wrong results. The same question as Append vs MergeAppend over sorted partitions. (Christian Del Monte · cdelmonte.dev)
  • Redis now has compressed bitmaps (Roaring) — an opt-in bitmap-roaring encoding due in Redis 8.12. The SETBIT string encoding allocates up to the highest offset, so one bit at offset 4 billion costs 512 MB and every BITOP scans all of it. (Daniel Lemire · lemire.me)
  • How we cut a ClickHouse delete from 12 s to under 2 — a lightweight DELETE walks every partition whatever its predicate matches, so one touching a single monthly partition was no faster than a full-window one (15–17 s). Yearly partitions brought p50 to 0.7–1.8 s; one-month reads then scanned about 7× the rows until the month moved into the sort key. (plutus-cloud.com)

Commercial engines (SQL Server, Oracle, MySQL, …)

  • When a small change writes too much: large folios vs mmap in PXC/Galera — after PXC 5.7→8.0 plus Debian 11→12 (kernel 5.10 → 6.1), Galera threads produced write bursts about every 33 s — 13 GB from appliers and 5.2 GB from the receiver in a few seconds — with InnoDB and binlog flat. (Przemysław Malkowski · percona.com)
    • gcache is mmap'd, and on XFS with large folios (5.18+) a dirty mmap page writes back the whole folio, up to 2 MB, instead of 4 KB; 6.6's per-block dirty tracking helps write()/pwrite() but not mmap
    • large readahead on RAID makes the folios bigger
    • workarounds: ext4 (folios only from 6.16), lower read_ahead_kb, MADV_RANDOM, or pwrite instead of mmap
  • MariaDB: 3.5× InnoDB regression on IN-list point lookups fixed (MDEV-37992) — a 100-value PK IN-list ran at about a third of 10.4's QPS from 10.5 on, with 18× more context switches per query. The fix stops nearly every access from moving the page to the head of the buffer-pool LRU (121M pages made "young" vs 343K after). The Foundation's reproduction measured 18–19k → 66–68k TPS on 11.8, 12.3 and 13.1. (Mark Callaghan; Alessandro Vetere · MariaDB JIRA / mariadb.org)
  • Fact-checking Microsoft's "PostgreSQL to SQL Field Notes: Connections" — Microsoft's series for Postgres developers moving to its "SQL" products claims 32,767 connections per instance. True, he says, only for connections that do nothing: what limits work is worker threads — 512 up to 4 cores, 512 + (cores − 4) × 16 up to 64 — and a parallel query takes DOP threads plus a coordinator per concurrent branch. His demo query on a 4-core box took 250 of the 512. Blocked queries keep their threads, so a THREADPOOL stall locks out monitoring too. A useful counterweight in the process-per-connection debate. (Brent Ozar · brentozar.com)
  • Thread pool in Percona Server and MySQL, part 2 — follows part 1, now on Community MySQL 26.7.0. At 2,560 connections with a 2 GB buffer pool, Percona's pool does 2,304 TPS against Oracle MySQL's 371; fully cached, the order flips (19,054 vs 15,519 TPS). Percona's is very sensitive to thread_pool_size/oversubscribe; Oracle's helps only from 1,280 connections. (Bogdan Degtyariov · percona.com) [single runs]
  • How we solved a rare Hyperdrive MySQL caching bug — protocol traps for a pooler: utf8 is utf8mb3; COM_RESET_CONNECTION resets the charset to the server default, not the one negotiated at handshake; mysql2 lacks CLIENT_DEPRECATE_EOF, so the proxy rewrites result-set terminators per client. The 0.001% empty-result bug came from two caches sharing a store in different capability encodings — a Postgres-era assumption that cached bytes equal bytes sent. (Pranoy Dutta · blog.cloudflare.com) [vendor blog — substantive]

Migration experience

  • Moving Copilot Studio's agent-flow backend to Azure Managed Redis — about 10–11k reads/s and 4k writes/s per geography. (devblogs.microsoft.com/powerplatform)
    • before moving, they found one cache path writing about 290M times a day for almost no reads, and a GET issued before the in-process cache was checked; fixing both cut server load in Europe from about 75% to 15%
    • cutover: dual-write of selected metadata to warm the target, per-process routing with planned restarts, health gates at each step
    • the Europe rollout failed and was rolled back: an inherited auth "maintenance listener" issued SUBSCRIBE, which broke the new service's backend-connection sharing and exhausted connections at production scale

Research & cutting edge

  • The case for single-version concurrency control in the cloud — a CIDR'27 position paper: with analytics offloaded to replicas or columnar engines, the OLTP writer no longer needs MVCC, whose version chains, GC and 16–32 B headers are all cost; rare long transactions get on-demand snapshot indexes. The only evidence is code size from LeanStore prototypes (303 vs 426 lines of core code); the ~35K-line figure for Postgres MVCC is "AI-estimated", and there are no performance numbers. (Nguyen, Haas, El-Hindi, Leis, Bernstein) [paper]
  • JetStream: generating verified query accelerators for existing DBMSs — LLM agents generate per-template accelerators over the host's own tables; on PG 18.4 changes are captured with statement-level triggers and transition tables, and verified variants carry Verus proofs. The headline 315× over DuckDB on TPC-H SF20 comes almost entirely from incrementally maintained per-query state — generated IVM, at 28.4 GB resident; stateless accelerators manage 2.1× over DuckDB and 4.4× over PG. (Balasingam, Ngom, Yu, Kraska) [paper]
  • Join order enumeration for double-star and helix join graphs — two star schemas sharing a spoke get a closed-form count of join orders and an exact C_out optimiser in O(a log a + b log b + ab) that beats DPhyp; the helix gets an exact count, but there the generic DP wins. (Taneja, Marcus) [paper]
  • ARCADE: retrofitting ABAC onto databases with an external policy engine — PostgreSQL and MySQL plugins send authorisation decisions to Cedar while the engine enforces them, on top of native DAC/RBAC; TPC-C overhead 1.3% on PG, 3.9% on MySQL. (Yelisetty, Sural et al.) [paper]
  • Recall-bounded staleness for filtered multi-tenant ANN graph indexes — splits recall loss into staleness and filtered navigability; on a merge-based graph, staleness "anti-amortizes" (20× larger merges cut recall@10 from 99.44% to 99.01%), and per-tenant staleness ceilings on FreshDiskANN remove tight-tier SLA violations. Relevant to background maintenance of vector indexes. (Das, Devadkar, Godbole) [paper]
  • Benchmarking content-defined chunking for deduplication — an ICDE 2027 paper that finds a long-standing parameterisation error in AE, copied across papers and tools, which makes chunks 13–39% smaller than intended and inflates its reported dedup ratio. (Gregoriadis, Balduf, Scheuermann, Pouwelse) [paper]

International (non-English sources)

  • How Postgres Pro got 1C:ERP to 30,000 users at APDEX 0.986 — three parts (2, 3) on more than 100 runs of a 20-scenario 1C:ERP load test; most DBMS fixes concern temporary tables, which 1C ANALYZEs every time it fills one. The fixes ship in their fork, but every bottleneck exists in stock PostgreSQL. (Postgres Professional · Habr) [ru] (orig: Как мы довели Postgres Pro до APDEX 0,986 на 30 000 пользователей 1С:ERP)
    • 15k users: ReceiveSharedInvalidMessages() topped the flamegraphs; not sending relcache/smgr/snapshot invalidations for temp objects, plus geqo off and higher collapse limits, moved APDEX from 0.841 to 0.933
    • 21k users: one pgstat entry per temp table drove LWLock:PgStatsHash/PgStatsDSA waits and rising DSA memory; excluding temp relations from relation stats removed both
    • temp tables and their indexes get no files until the first real write — up to 3M files created and deleted at 30k sessions
    • 30k users: inserts waited 20–33 s on the relation-extension lock, whose holder was starved on BufferMapping by shared holders; a cap on shared acquisitions while an exclusive waiter queues fixed it
  • UniqueKeys: teaching the planner where rows are unique — a walk through Richard Guo's patch (CF #7045, waiting on author). Each RelOptInfo carries keys stored as EquivalenceClasses with a null_aware flag: a nullable UNIQUE column can prove Inner Unique for a strict join but can't justify dropping a DISTINCT. Keys survive a join when the other side is unique on the join clause, lose null_aware on the nullable side of a LEFT JOIN, and FULL JOIN derives nothing. Effects shown in plans: DISTINCT over a PK disappears, Inner Unique is proven when the inner side is itself a join, semi-joins skip unique-ification. Capped at 8 keys per relation. (pg_ilia · Tantor Labs on Habr) [ru] (orig: UniqueKeys — планировщик PostgreSQL учится помнить, где строки уникальны)
  • Which Spanner bugs Omni catches and the emulator misses — one test suite run against the Spanner emulator, Spanner Omni 2026.r4-lts on a single 4-vCPU server, and a free Cloud Spanner instance as ground truth, with judging rules committed before the first run and raw data on GitHub. Omni matched production where the emulator didn't on concurrent read-write transactions without aborts, PLAN/PROFILE, ANALYZE, drop protection, the 10 MiB cell limit (actually 10 MiB − 4 bytes) and crash durability. It still diverges on mutation limits (120,000 per commit vs 80,000) and version_retention_period. No performance numbers: Omni's licence forbids publishing benchmarks without consent. (Shinya Koike · Zenn) [ja] (orig: Spanner Omniで捕まるバグ、捕まらないバグ)
  • ClickHouse now defaults to ZSTD(3): what is still worth tuning? — ClickHouse 26.9 switched the default codec from LZ4 to ZSTD(3); first 10M rows of ClickBench hits, 26.8 vs 26.9. Compressed size fell 35% (1,365 → 884 MiB), but parts under 100 MB still get LZ4, so after a fresh load all 22 parts were LZ4 and existing data shrinks only when rewritten. Delta on time columns was the only codec worth adding (−28%); Delta or T64 on hash columns made them 30–90% larger. Hot-cache queries ran 5–35% slower under ZSTD, worst on long-string scans. (skillogy · Qiita) [ja] (orig: ClickHouseの圧縮最適化は、ZSTDが既定になっても必要か?1,000万行で検証)
  • Why converting an OceanBase table to dynamic partitioning leaves expired partitions behind — on 4.4.2.2, the first MANAGE_DYNAMIC_PARTITION run added 23 monthly partitions but kept seven already-expired ones it had just created: the drop step builds its expiry list from a schema snapshot taken before the ADD PARTITION. A second run cleans up; TIME_UNIT can't be changed after conversion. (瑞蓝创软件 · OceanBase community) [zh] (orig: OceanBase 非动态分区表转动态分区,过期的分区不会自动删除?)

Call for papers

Upcoming events

  • pgDay México 2026 — Mexico City, 13 November — one day, mostly in Spanish. Internals picks:
    • Why Did My Query Plan Change? Diagnosing and Stabilizing PostgreSQL Query Plans (Suman Michael) — plan flips and pinning, timely with pg_plan_advice shipping in 19.
    • pg_stat_login: real-time authentication statistics inside PostgreSQL (Anthony Sotongo) — counters for the auth path, which core doesn't have.
  • PGConf.Asia 2026 — Hong Kong, 17–18 November — preliminary schedule posted. Internals picks:
    • True In-Place Upgrades in PostgreSQL (John Naylor) — what it would take to remove pg_upgrade's catalog dump/restore step.
    • Teaching B-Trees to Merge: A Concurrent Solution to Index Bloat (Salma Elsayed) — online merging of underfull nbtree pages, which nbtree doesn't do today.
    • SNAPLock: Improving PostgreSQL Throughput under Linux 7.0 Full Preemption (Atsushi Mitani) — spinlock and LWLock behaviour once the kernel can preempt a lock holder.

New sources added this week

  • materialize.com/blog — storage-layer engineering on Postgres as a metadata store, with formal proofs.
  • depesz.com — long-running, reproducible Postgres measurements. (Hubert 'depesz' Lubaczewski)
  • lakehousebox.com/blog — measured DuckDB/Iceberg benchmarks that report regressions too.
  • cdelmonte.dev — source-level DataFusion planner explainers. (Christian Del Monte)
  • lemire.me — compressed bitmaps, SIMD and parsing, by the Roaring author. (Daniel Lemire)

70 items · yield — mailing lists: 1,107 messages in window (712 hackers / 101 bugs / 0 performance / 49 general, plus 235 pgsql-committers and 10 pgsql-announce) → 40 shortlisted → 20 published · blogs: ~148 posts in window → 85 shortlisted → 26 published · community: ~165 threads viewed → 21 shortlisted → 3 published · research: 35 cs.DB preprints announced in window → 13 shortlisted → 6 published · international: ru 20→4→2, zh 26→7→1, ja ~125→5→2, de 4→1→0, fr 0→0→0 (polyglot search unavailable this run; native feeds and APIs, native-language web search and the browser used instead).