Contents
Changelog
All notable changes to ulak will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.0 (2026-11-12)
⚠ BREAKING CHANGES
- redis: TLS connections fail when the server certificate does not match the configured host. OOM and READONLY replies are retried instead of going to the DLQ.
- nats: Nats-Msg-Id is ulak-
- amqp: an unroutable mandatory publish is retried instead of completing. The message_id property is msg_
- mqtt: ulak.mqtt_default_qos defaults to 1. With ulak.workers > 1 a configured client_id gets a _
- http: HTTP 408 and 425 responses are retried instead of going to the DLQ.
- worker: a row found stuck in ‘processing’ is charged a retry and moves to the DLQ once its retries are used up. A worker ended with pg_terminate_backend() is restarted after ulak.worker_restart_delay. Worker sessions run with synchronous_commit = local and lock_timeout = 10s.
- sql: send_with_options(), send_batch(), send_batch_with_priority(), publish() and publish_batch() reject a payload larger than ulak.max_payload_size (SQLSTATE 54000), and send_batch() / send_batch_with_priority() count every row against ulak.max_queue_size (SQLSTATE 53400).
Features
- mqtt: report publishes the broker refuses on MQTT 5 connections (6e4002c)
Bug Fixes
- amqp: fail returned mandatory publishes and bound broker RPCs (b932935)
- core: keep the trigger wake-up after a send() that failed (ad4eafb)
- core: start two timeout GUCs at their boot values (f787d77)
- http: extend the SSRF guard to IPv6, NAT64 and broadcast addresses (b7f5190)
- http: retry 408 and 425, keep batch-mode headers and Retry-After (7683656)
- http: size the OAuth2 token buffer to the response (f78faa9)
- kafka: tie sync reports to their produce and accept acks 0 and 1 (b902767)
- mqtt: publish with QoS 1 by default and bound the connect (c886bcb)
- nats: retry publishes no stream takes and namespace Nats-Msg-Id (7024104)
- redis: check the TLS host name and retry OOM and READONLY (6165e0e)
- sql: apply payload and queue limits on every enqueue function (86c97e8)
- sql: name the members of each ulak role in the uninstall script (3ab3269)
- sql: refuse to run the extension scripts through psql (dffe8e5)
- sql: warn when the ulak roles already exist with members (04a6c78)
- worker: keep delivering through errors, stuck rows and restarts (8174c7b)
Performance Improvements
- core: keep senders off the registry lock in the backpressure check (7b2b420)
0.2.0 (2026-09-09)
⚠ BREAKING CHANGES
- worker: the queue trigger and the send_batch/publish functions no longer issue NOTIFY ‘ulak_new_msg’. External processes that LISTEN on that channel to learn about new messages must set ulak.wake_notify = on (the NOTIFY is then throttled per session by ulak.notify_throttle_ms) or fall back to polling.
Features
- worker: wake workers through shared memory at commit instead of NOTIFY (27c2e26)
Bug Fixes
- redis: bound host name resolution by connect_timeout (9e92878)
- worker: claim in one transaction, deliver, then write results in another (a089c8e)
0.1.2 (2026-09-08)
Bug Fixes
0.1.1 (2026-09-07)
Bug Fixes
- docker: install every runtime library ulak.so needs in the published image (6a1df54)
- docker: install every runtime library ulak.so needs in the published image (de15b93)
0.1.0 (2026-09-07)
⚠ BREAKING CHANGES
- sql: ulak_application and ulak_monitor lose SELECT on ulak.endpoints (use ulak.endpoint_status); ulak.prevent_payload_modification() is removed; redrive_message() raises for DLQ rows that are not in failed state.
- core: ulak.database requires a server restart to change (pg_reload_conf no longer applies it), and metrics() no longer returns spawns_total, spawn_failures_total or restarts_total.
Features
- sql: endpoint_status view, tighter grants, single queue trigger and 0.1.0 upgrade path (0ffc72e)
Bug Fixes
- http: stable webhook ids, whsec_ secrets, stricter SSRF guard and 4xx handling (9f2d3d4)
- kafka: fix use-after-free in batch growth and stale delivery callbacks (cdc4aec)
- mqtt: wait for the broker acknowledgement on synchronous QoS ½ publishes (52a4059)
- nats: confirm JetStream publishes via AckHandler instead of dropping errors (02ae498)
- nats: require the result buffer in dispatch_ex (2f85dcb)
- resolve v0.0.3 review findings and prepare the 0.1.0 upgrade path (64aafb5)
- worker: drain LISTEN queue, defer rate-limited rows and expire messages (948ed2f)
Code Refactoring
- core: remove dead launcher, DSM and entity layers; log endpoint DDL at LOG level (6438255)
Documentation
- readme: link test directories with relative paths (19aca5c)
Continuous Integration
- fail the clang-tidy gate on errors and suppress cppcheck’s branch-limit notice (73b1d31)
Miscellaneous
- release: list every commit type in the changelog (f8b29ae)
- release: verify the extension upgrade chain reaches the released version (569fa79)
0.0.3 (2026-05-12)
Bug Fixes
0.0.2 (2026-04-15)
Bug Fixes
- add manual trigger to Docker publish workflow (dfa5fa8)
0.0.1 (2026-04-15)
Features
- initial commit (a928cf0)
[0.0.0]
Added
- Core transactional ulak with
send(),send_with_options(),send_batch(), andsend_batch_with_priority()functions. - Pub/Sub system with
publish(),publish_batch(), event types, and subscriptions. - Six protocol dispatchers: HTTP (always enabled), Kafka, MQTT, Redis Streams,
AMQP, and NATS (conditional compilation via
ENABLE_*flags). - Batch dispatch support for Kafka, MQTT, and AMQP with async produce/flush.
- Multi-worker background processing with modulo-based queue partitioning
(
bgw_main_arg = (total_workers << 16) | worker_id). - Circuit breaker per endpoint with configurable threshold and cooldown.
- Dead-letter queue (DLQ) with
redrive_message(),redrive_endpoint(),redrive_all(), anddlq_summary(). - Monthly-partitioned archive table with
replay_message()andreplay_range(). - Backpressure control via
max_queue_sizeGUC. - GUC parameters covering core, retry, circuit breaker, HTTP, Kafka, Redis, MQTT, AMQP, NATS, data retention, and response capture.
- RBAC with three roles:
ulak_admin,ulak_application,ulak_monitor. - HTTP dispatcher with libcurl, curl_multi batching, SSRF protection, OAuth2, SigV4, and Bearer/Basic/API-key authentication.
- Kafka dispatcher with librdkafka, delivery reports, and batch produce.
- MQTT dispatcher with libmosquitto, QoS levels, and PUBACK-based batch mode.
- Redis Streams dispatcher with hiredis, TLS support, and consumer groups.
- AMQP dispatcher with librabbitmq, publisher confirms, and batch produce.
- NATS dispatcher with Core NATS / JetStream publishing and batch flush support.
- Shared memory worker registry with LWLock coordination.
- LISTEN/NOTIFY integration for low-latency message wake-up.
FOR UPDATE SKIP LOCKEDconcurrent queue consumption.- Ordering key support for per-key sequential delivery.
- Idempotency key support with conflict detection.
- Scheduled message delivery via
scheduled_atparameter. - Message TTL with automatic expiration via
mark_expired_messages(). - CloudEvents envelope support for HTTP dispatcher.
- Webhook HMAC signature verification.
- 27 regression tests, 12 isolation tests, and 3 TAP tests with
make installcheck. - Docker Compose development environment with all protocol services.
- GitHub Actions CI for PostgreSQL 14-18 testing and static analysis.
This entry describes the initial contents of version 0.0.0.