ulak

Transactional Outbox extension for PostgreSQL with reliable asynchronous delivery

Overview

PackageVersionCategoryLicenseLanguage
ulak0.0.2FEATApache-2.0C
IDExtensionBinLibLoadCreateTrustRelocSchema
2680ulakNoYesYesYesNoNoulak

preload required

Version

TypeRepoVersionPG VerPackageDeps
EXTPIGSTY0.0.21817161514ulak-
RPMPIGSTY0.0.21817161514ulak_$v-
DEBPIGSTY0.0.21817161514postgresql-$v-ulak-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
d13.x86_64
d13.aarch64
u22.x86_64
u22.aarch64
u24.x86_64
u24.aarch64

Build

You can build the RPM / DEB packages for ulak using pig build:

pig build pkg ulak         # build RPM / DEB packages

Install

You can install ulak directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install ulak;          # Install for current active PG version
pig ext install -y ulak -v 18  # PG 18
pig ext install -y ulak -v 17  # PG 17
pig ext install -y ulak -v 16  # PG 16
pig ext install -y ulak -v 15  # PG 15
pig ext install -y ulak -v 14  # PG 14
dnf install -y ulak_18       # PG 18
dnf install -y ulak_17       # PG 17
dnf install -y ulak_16       # PG 16
dnf install -y ulak_15       # PG 15
dnf install -y ulak_14       # PG 14
apt install -y postgresql-18-ulak   # PG 18
apt install -y postgresql-17-ulak   # PG 17
apt install -y postgresql-16-ulak   # PG 16
apt install -y postgresql-15-ulak   # PG 15
apt install -y postgresql-14-ulak   # PG 14

Preload:

shared_preload_libraries = 'ulak';

Create Extension:

CREATE EXTENSION ulak;

Usage

Sources: README, wiki, v0.0.2 release

ulak implements the transactional outbox pattern inside PostgreSQL. Messages are inserted transactionally, then background workers deliver them asynchronously with retries, circuit breaking, and dead-letter handling.

Enable the Extension

-- postgresql.conf
shared_preload_libraries = 'ulak'

CREATE EXTENSION ulak;

The README also shows setting ulak.database when running the included Docker example.

Define Endpoints and Send Messages

SELECT ulak.create_endpoint(
  'my-webhook',
  'http',
  '{"url":"https://httpbin.org/post","method":"POST"}'::jsonb
);

BEGIN;
  INSERT INTO orders (id, total) VALUES (1, 99.99);
  SELECT ulak.send('my-webhook', '{"order_id":1,"total":99.99}'::jsonb);
COMMIT;

The same API pattern is documented for kafka, mqtt, redis, amqp, and nats endpoints.

Delivery Controls and Pub/Sub

SELECT ulak.send_with_options(
  'my-webhook',
  '{"event":"order.created"}'::jsonb,
  5,
  NOW() + INTERVAL '10 minutes',
  'order-123-created',
  '550e8400-e29b-41d4-a716-446655440000'::uuid,
  NOW() + INTERVAL '1 hour',
  'order-123'
);

SELECT ulak.send_batch('my-webhook', ARRAY['{"id":1}'::jsonb, '{"id":2}'::jsonb]);

SELECT ulak.create_event_type('order.created', 'New order placed');
SELECT ulak.subscribe('order.created', 'my-webhook');
SELECT ulak.publish('order.created', '{"order_id":123}'::jsonb);

Monitoring and Recovery

SELECT * FROM ulak.health_check();
SELECT * FROM ulak.get_worker_status();
SELECT * FROM ulak.get_endpoint_health();
SELECT * FROM ulak.dlq_summary();

SELECT ulak.redrive_message(42);
SELECT ulak.redrive_endpoint('my-webhook');
SELECT ulak.redrive_all();
SELECT ulak.replay_message(100);

Key Settings

The README highlights these ulak. GUCs:

  • workers
  • poll_interval
  • batch_size
  • max_queue_size
  • circuit_breaker_threshold
  • circuit_breaker_cooldown
  • http_timeout
  • dlq_retention_days

The v0.0.2 release notes only document a Docker publish workflow fix, so the current README and wiki remain the authoritative user-facing usage sources.


Last Modified 2026-04-19: update extension stub docs (9f178c3)