MERGE PARTITIONS and SPLIT PARTITION are back in PostgreSQL 19. They were merged for PostgreSQL 17, reverted before GA, and have spent a year in rework. The version landing in 19 takes a heavier lock than the original and makes fewer ambitious promises. This is the right outcome, and the story of how it got here is worth understanding if you care about how the project actually decides things.
What the feature does
ALTER TABLE ... MERGE PARTITIONS takes two or more partitions of a partitioned table and combines them into one. ALTER TABLE ... SPLIT PARTITION takes one partition and divides it into multiple, with new partition bounds. Before this, you did this dance manually: create the new partition, copy data, swap, drop. Slow, error-prone, and a known sharp edge of the partitioning model.
In PG19, both operations are single DDL statements. The tradeoff is that both take an AccessExclusiveLock on the parent table for the entire operation. While the merge or split runs, no SELECT, no INSERT, no anything against the partitioned table.
Why the first attempt got reverted
The original PG17 patches were ambitious. They tried to do these operations with finer-grained locking — locking the affected partitions but allowing access to the rest of the table. That is the right design eventually. It is not the design that was ready in late 2024.
I was not in the room for the discussions that led to the revert (almost nobody was; this is a mailing-list project), and the post-mortem on pgsql-hackers was characteristically terse. The shape of the problem was clear enough from the public discussion: deadlock potential between the partition operation and concurrent queries traversing the partition descriptor cache, edge cases around default partitions and what happens when a partition that is being split or merged also contains rows that should now route somewhere else, foreign key handling across the operation boundary, and the usual collection of “what does ANALYZE see during this” questions. Each of these is solvable. None of them was solved enough to ship.
The decision to revert late in the cycle was the right one and is also the kind of decision that happens more often in PostgreSQL than people realize. The community has a strong preference for shipping a feature that is slow but correct over shipping one that is fast and possibly broken. This is not a universal preference in database engineering — plenty of vendors will ship the fast version and patch around the breakage in subsequent releases. The PostgreSQL project does not work that way, and PG19’s partition merge/split is a clean example of why.
What changed
The PG19 version sidesteps the concurrency hazards by simply not being concurrent. The parent-table AccessExclusiveLock is the simplest possible answer to “what if a query is in flight against a partition I’m about to dissolve” — there are no in-flight queries.
This is intellectually unsatisfying but operationally honest. The feature is shipped, the semantics are clear, and the locking is something you can plan around. A future release will reduce the lock scope. That work is queued. The first attempt’s mistake was trying to do both things at once.
What this means operationally
For most workloads, the operations will be feasible during a maintenance window and infeasible during peak traffic. The merge or split has to physically reorganize data — for a SPLIT, every row in the source partition has to be examined to determine its new partition; for a MERGE, the data has to be unified — and the time scales linearly with partition size.
A partition of, say, 100 GB on reasonably fast storage will take long enough that you do not want to be holding AccessExclusiveLock on the parent table during business hours. A partition of 5 GB might be acceptable in a quiet window. The operational math is straightforward: estimate the time to rewrite the partition data, multiply by some safety factor, that’s your lock window.
If you can’t afford that lock window, the manual dance is still available, and frankly is still what I’d recommend for any partition that is large or any table that is hot. The new commands are a real improvement for the common case of “I’m doing partition maintenance off-hours and I don’t want to write the dance script again.” They are not a tool for online repartitioning of busy tables. The release notes will be clear about this. The blog posts that summarize the release notes may not be.
What to do
If you do partition maintenance regularly and you’ve been carrying scripts to do it manually, you can stop carrying those scripts after you upgrade to PG19. The new commands do exactly what the scripts did, less the chance of typos.
If you’re hoping for online partition reorganization, this isn’t it. Wait for the next round of work, which based on the current pgsql-hackers traffic is likely to land in PG21 at the earliest.
If you’re considering migrating to declarative partitioning specifically because the merge/split operations are now in core: this is a fine reason. Do not let it be the only reason. The other partitioning sharp edges (no global indexes, no global unique constraints across partition keys, planning costs at large partition counts) are still there.
The feature is good. The design tradeoff is the right one. The story behind the design tradeoff is the more interesting part.