PostgreSQL prevents detaching a partition when active transactions or queries are accessing the partitioned table. This happens because the DETACH operation needs locks that conflict with running queries. Use DETACH PARTITION CONCURRENTLY (PostgreSQL 14+) or wait for transactions to complete.
Error 55006 occurs when you attempt to detach a partition from a partitioned table while that partition (or its parent table) is in active use by other transactions or queries. PostgreSQL requires exclusive locks on the partitioned table to safely detach a partition, and these locks conflict with any ongoing read or write operations. This is a safety mechanism to prevent data corruption and ensure consistency. The error message "Cannot detach partition in use" indicates that PostgreSQL cannot acquire the necessary Access Exclusive lock on either the partition being detached (in older versions) or the parent table (in all versions), because other sessions are actively using the table. This commonly occurs in production environments where queries are continuously running against the partitioned table.
First, identify which transactions are blocking the DETACH operation:
SELECT pid, usename, application_name, state, query, query_start
FROM pg_stat_activity
WHERE datname = current_database()
AND state != 'idle'
ORDER BY query_start;This query shows all non-idle connections. Look for any queries accessing your partitioned table. The query_start column shows how long the query has been running.
Check which locks are currently held and which are being waited for:
SELECT l.pid, l.mode, l.granted, a.usename, a.query
FROM pg_locks l
JOIN pg_stat_activity a ON l.pid = a.pid
WHERE l.relation = 'your_table'::regclass
ORDER BY l.granted DESC;Replace your_table with your partitioned table name. Locks with granted = false are waiting for access, while granted = true are holding locks.
If you identify transactions that can be safely terminated, kill them:
-- For a single blocking session
SELECT pg_terminate_backend(12345); -- Replace 12345 with the PID
-- For all idle transactions
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = current_database()
AND state = 'idle in transaction'
AND pid != pg_backend_pid();Be very cautious: terminating transactions can cause data loss or application errors. Only terminate sessions you are certain can be safely killed.
If you are running PostgreSQL 14 or later, use the CONCURRENTLY option to minimize lock duration:
ALTER TABLE parent_table
DETACH PARTITION partition_name CONCURRENTLY;This operation uses SHARE UPDATE EXCLUSIVE lock instead of Access Exclusive, allowing other transactions to continue reading and writing to the parent table (including other partitions). CONCURRENTLY cannot be used in a transaction block—run it as a standalone statement. It also cannot be used if the partitioned table has a default partition.
The CONCURRENTLY detach runs in two transactions:
1. First transaction marks the partition as detached in the catalog
2. Second transaction waits for older snapshots to clear and completes the detach
This ensures consistency while minimizing blocking.
If running PostgreSQL < 14, you must wait for all active transactions to complete before DETACH can proceed. During low-traffic periods:
1. Monitor activity to confirm no long-running queries:
SELECT COUNT(*) FROM pg_stat_activity
WHERE datname = current_database() AND state != 'idle';2. Once the count is 0 or only idle transactions remain, attempt DETACH:
ALTER TABLE parent_table
DETACH PARTITION partition_name;3. Consider draining application connections before the DETACH to reduce wait time.
If a concurrent detach was cancelled or crashed mid-operation, complete it with:
ALTER TABLE parent_table
DETACH PARTITION partition_name FINALIZE;This finishes the second transaction of a previously started concurrent detach operation.
PostgreSQL Versions and Locking: Prior to PostgreSQL 14, DETACH PARTITION acquires Access Exclusive lock on both the partition and the parent table, effectively freezing all access to all partitions until the operation completes. This is why "cannot detach partition in use" is such a severe issue in pre-14 deployments. PostgreSQL 14 introduced DETACH PARTITION CONCURRENTLY which uses only SHARE UPDATE EXCLUSIVE lock on the parent, allowing concurrent reads and writes. For production systems with continuous traffic, always upgrade to PostgreSQL 14+ if partition detachment is a regular operation.
Deadlock with DETACH CONCURRENTLY: In rare cases, DETACH PARTITION CONCURRENTLY can cause deadlocks with SERIALIZABLE or REPEATABLE READ transactions due to snapshot consistency checks (WaitForOlderSnapshots). If you encounter persistent deadlocks with concurrent detach, switch temporarily to non-concurrent detach during maintenance windows, or use SERIALIZABLE isolation on the fewest possible transactions.
Partitioned Tables with Foreign Keys: If the partitioned table has a foreign key constraint that references itself (where the partition key is part of the FK), PostgreSQL may prevent detach even if no data violations exist. The workaround is to drop the global FK, detach the partition, then rebuild independent FKs on each partition if needed.
Application Connection Pools: ORM connection pools and database drivers often maintain open transactions automatically. If you cannot identify blocking queries, check your application's connection pool settings. Tools like pgBouncer can help manage connections, and consider setting idle_in_transaction_session_timeout to automatically terminate idle transactions.
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
No SSL connection
No SSL connection to PostgreSQL