Compatibility
July 26, 2026 ยท View on GitHub
Support policy
pgmq-cpp v1.0 has one full-support server baseline:
| Layer | Supported |
|---|---|
| PostgreSQL | 14, 15, 16, 17, 18 |
| PGMQ | 1.12.0 |
| Installation form | PostgreSQL extension recorded in pg_extension |
| Upstream source reference | v1.12.0 at 08ace4087dbf00e51704c5a3d9df2e15fd566127 |
The PostgreSQL range follows the upstream PGMQ v1.12.0 support statement. The current SDK and worker integration suites also passed on each PostgreSQL major from 14 through 18 with PGMQ 1.12.0 and pg_partman 5.1.0. Exact server version numbers, immutable image digests, commands, and platform boundaries appear in verification.md.
PGMQ's SQL-only installation is not supported in v1.0. Although it creates
many of the same schema objects, Client::capabilities() deliberately requires
the installed version from pg_extension. This fails closed instead of
guessing which SQL bundle was applied.
Why PGMQ 1.12.0 is the baseline
The public message record and the SDK's full feature set span multiple PGMQ
releases. In particular, current records contain last_read_at and headers,
and v1.12.0 completes long-poll support for the grouped-head FIFO strategy.
The client inspects exact function signatures and result fields with
to_regprocedure and the PostgreSQL catalogs. Those flags are useful for
diagnostics and for rejecting selected unsupported operations. They do not
make all older combinations supported: several core parsing paths intentionally
target the current seven-field pgmq.message_record.
After upgrading PGMQ in place, construct a new Client. Capabilities are
cached for the lifetime of a client instance.
Capability mapping
ServerCapabilities field | Catalog probe / meaning |
|---|---|
batch_send | pgmq.send_batch(text,jsonb[],jsonb[],integer) |
batch_delete | pgmq.delete(text,bigint[]) |
batch_archive | pgmq.archive(text,bigint[]) |
batch_set_visibility | pgmq.set_vt(text,bigint[],integer) |
read_with_poll | long-poll read with conditional JSON parameter |
message_headers | four-argument pgmq.send with JSON headers |
notifications | throttled two-argument enable_notify_insert |
notification_throttling | update_notify_insert |
fifo_grouped | grouped FIFO read |
fifo_grouped_poll | grouped FIFO long-poll read |
fifo_round_robin | round-robin grouped FIFO read |
fifo_round_robin_poll | round-robin grouped FIFO long-poll read |
fifo_group_heads | one visible head per message group |
fifo_group_heads_poll | grouped-head long-poll read |
topics | topic send/routing functions |
topic_batch | batch topic send |
conditional_read | four-argument standard read |
visible_metrics | queue_visible_length in metrics_result |
The returned structure also includes parsed PostgreSQL/PGMQ versions and
server_version_num.
Upstream feature history
This table documents where relevant upstream SQL first appears in the
v1.12.0 upgrade chain. It is not a promise that pgmq-cpp supports each older
release as a complete runtime.
| Upstream PGMQ | Relevant addition |
|---|---|
| 1.5.0 | headers, conditional read, visible queue length, current header-aware batch send family |
| 1.7.0 | initial unthrottled insert notifications |
| 1.8.0 | notification throttling/config table and batch visibility update |
| 1.9.0 | grouped and grouped-round-robin FIFO reads, their polling forms, FIFO indexes |
| 1.10.0 | last_read_at in queue/archive records and current message-record shape |
| 1.11.0 | topics/routing, batch topic send, notification throttle update, revised concurrent read functions |
| 1.11.1 | grouped-head FIFO read |
| 1.12.0 | grouped-head FIFO read with polling |
Always prefer the capability booleans over hard-coded application-side version comparisons.
Public operation coverage
| Area | v1.0 SDK entry points | PGMQ 1.12.0 |
|---|---|---|
| Version/capabilities | Client::capabilities | Supported |
| Queue lifecycle | create/drop/purge/list, FIFO indexes, archive partition conversion | Supported; conversion requires pg_partman |
| Queue storage | durable, unlogged, partitioned | Supported; partitioned requires pg_partman |
| Send | JSON/raw, single/batch, relative/absolute delay, headers | Supported |
| Read | standard, conditional, targeted by id, long poll | Supported |
| FIFO read | grouped, round-robin, grouped-head, polling variants | Supported |
| Destructive read | pop single/batch | Supported; at-most-once risk |
| Completion | delete/archive single/batch | Supported |
| Visibility | single/batch relative and absolute | Supported |
| Metrics | one/all, including visible length | Supported |
| Notifications | enable/update/disable/list/listen | Supported with limitations below |
| Topics | validate/bind/unbind/list/test/send/batch send | Supported |
| Dead-letter replay | guarded single/batch replay; destination send and DLQ delete are atomic after selection | Supported for pgmq-cpp.dead-letter.v1 envelopes |
| Transactions | send/read/delete/archive/visibility plus parameterized business SQL | Supported |
Notification limitations
PGMQ v1.12.0 emits on pgmq.q_<lowercase_queue>.INSERT with an empty payload.
The throttle interval is non-negative:
250 msis the SDK and upstream default;0 msdisables PGMQ throttling;- a positive value suppresses repeated trigger notifications inside that interval.
Even with a zero throttle, notification count is not message count.
PostgreSQL can coalesce identical channel/payload notifications in one
transaction, delivers notifications only after commit, and does not retain
them for disconnected listeners. A reconnect also has a race before LISTEN
is restored. The runtime therefore treats every notification as an advisory
wake-up and keeps periodic reads enabled.
Notification setup requires PGMQ's trigger/config functions and suitable database privileges. If notification setup or listening fails, the worker continues through polling. This may increase idle query frequency and pickup latency but must not lose queue work.
Queue and routing constraints
- A
QueueNamecontains 1โ47 lowercase ASCII letters, digits, or underscores:[a-z0-9_]+. Under this boundary, bytes and characters have the same count. - This is deliberately stricter than PGMQ's public validator. PGMQ 1.12 preserves input spelling in some metadata and notification configuration while physical table and trigger-channel names are lowercase. Accepting uppercase would therefore permit case aliases and silent notification mismatches. v1.0 rejects uppercase and does not support pre-existing uppercase queue names.
- Default DLQ names are
<source>_dlqwhen that fits. Longer source names use a truncated prefix and stable hash; an explicitly configured DLQ must differ from its source queue. - FIFO grouping uses the
x-pgmq-groupheader. Messages without it share the upstream default group. - Topic routing patterns and keys are validated by PGMQ. Routing is a database operation; the SDK does not duplicate the upstream pattern compiler.
Clock semantics
- Regular-worker lease scheduling subtracts the database-observed timestamp
from the database visibility timestamp and maps the remaining duration onto
steady_clock. - Regular and transactional retry bind validated
bigintmillisecond durations; PostgreSQL computes each new visibility timestamp fromclock_timestamp(). - Regular and transactional retry durations are limited to the inclusive
range
0..9,007,199,254,740 ms. This project-enforced bound keeps the float8-backed PostgreSQL interval calculation at or below2^53internal microseconds, preserving exact integer milliseconds. Negative or larger values fail asinvalid_inputwith operationworker_retrybefore visibility SQL is issued. - Neither path requires the application host wall clock to match the database clock.
- Caller-supplied absolute enqueue and visibility
TimePointvalues are still absolute wall-clock instants. Their meaning is only as correct as the instant supplied by the caller.
Build compatibility
The package requires a C++20 standard library, CMake 3.25+, libpq, and nlohmann/json. The source defines MSVC and GCC/Clang warning profiles, plus a Linux ASan/UBSan preset.
Observed v1.0.0 acceptance coverage is:
| Platform | Compiler/configuration | Libraries | Evidence |
|---|---|---|---|
| Windows | MSVC 19.41, Debug and Release, /W4 /WX | static and shared | all targets and all eight CTest entries passed in each of four fresh builds |
| Windows Server 2022 hosted | MSVC 19.44.35228, Release, /W4 /WX | static, vcpkg x64-windows | GitHub-hosted unit and installed consumer passed 2/2 |
| Ubuntu 24.04 | GCC 13.3 Debug, warnings as errors | static | all targets plus unit and installed consumer passed |
| Ubuntu 24.04 | Clang 18.1 Release, warnings as errors | static and shared | all targets plus unit and installed consumer passed; shared consumer also ran from /tmp using its installed-prefix RUNPATH |
| Ubuntu 24.04 | GCC 13.3 and Clang 18.1 Debug | sanitizer builds | ASan/UBSan builds and unit execution passed |
| macOS 15.7.7 ARM64 hosted | Apple Clang 17.0.0 / Xcode 16.4 | static, vcpkg arm64-osx | GitHub-hosted build, unit, and installed consumer passed 2/2 with the verified -fexperimental-library path |
Strict clang-tidy and Doxygen also passed in the Ubuntu 24.04 validation image.
The first GitHub-hosted run exposed Linux documentation, Windows shell syntax,
and macOS standard-library portability defects. After fixes, run
30200789701 passed all five jobs on one source commit, including real PGMQ
integration, ASan/UBSan, clang-tidy, Doxygen, and both hosted package
consumers.
Docker-backed integration tests are opt-in for a direct CMake configure. The project's Windows debug/release and Linux debug presets enable them explicitly; the Linux sanitizer preset does not.
The installed CMake package exports:
pgmq::clientpgmq::worker
No libpq type appears in the public API.
The vcpkg manifest is pinned to builtin baseline
40f3c709db80acf154ac4b17a1f83c564ebd022e and declares libpq and
nlohmann-json. A clean bootstrap of that baseline installed the public
dependencies successfully. Project-local checkout/cache directories are test
infrastructure, not package dependencies.