Quick Start
This guide shows the shortest path from a PostgreSQL table change to a Mammoth webhook delivery.
For a one-command, application-level walkthrough with a browser UI, signed
receiver, visible retries, health endpoints, and an adaptation guide, start
with ../webhooks-quickstart. Continue here when you
want to assemble the same pieces manually.
1. Install Mammoth
From RubyGems:
gem install mammoth
Or use the container image:
docker pull ghcr.io/kanutocd/mammoth:latest
2. Prepare PostgreSQL
PostgreSQL must be configured for logical replication.
At minimum, PostgreSQL needs:
wal_level = logical
max_replication_slots > 0
max_wal_senders > 0
Create a table and publication:
CREATE TABLE IF NOT EXISTS orders (
id bigserial PRIMARY KEY,
status text NOT NULL,
total_cents integer NOT NULL
);
CREATE PUBLICATION mammoth_publication FOR TABLE orders;
The primary key supplies replica identity for published UPDATE and DELETE
operations. Mammoth validates this before streaming; an eligible selected
unique index or REPLICA IDENTITY FULL is also supported.
Create a replication user according to your local security policy. For local development, examples may use a simple user/password setup.
3. Configure Mammoth
Create a Mammoth config file:
# yaml-language-server: $schema=./mammoth.schema.json
mammoth:
name: local_mammoth
postgres:
host: localhost
port: 5432
database: app_development
username: mammoth
password_env: MAMMOTH_POSTGRES_PASSWORD
replication:
slot: mammoth_prod
publications:
- mammoth_publication
auto_create_slot: true
temporary_slot: false
feedback_interval: 10.0
delivery:
unit: transaction
ordering:
scope: transaction
runtime:
adapter: concurrent
concurrency: 1
preserve_order: true
timeout_seconds:
webhook:
name: primary_webhook
url: http://localhost:9292/webhook
timeout_seconds: 5
retry:
max_attempts: 5
schedule_seconds:
- 1
- 5
- 30
- 60
- 300
sqlite:
path: data/mammoth.db
logging:
level: info
Mammoth checkpoints only contiguous durable delivery outcomes and then
acknowledges the same progress through pgoutput-client. The feedback interval
controls transport cadence, not which position is safe.
auto_create_slot: true creates a missing slot only for first-time bootstrap
while no resume LSN or checkpoint exists. Later restarts preflight the retained
slot and fail closed if checkpoint continuity is unavailable.
Export the password referenced by postgres.password_env:
export MAMMOTH_POSTGRES_PASSWORD=secret
If your receiver requires authentication, add env-backed headers instead of placing secrets directly in YAML:
webhook:
header_env:
Authorization: MAMMOTH_WEBHOOK_AUTHORIZATION
signing:
algorithm: hmac_sha256
secret_env: MAMMOTH_WEBHOOK_SIGNING_SECRET
4. Validate configuration
mammoth validate config/mammoth.yml
When running from the repository checkout:
bundle exec ./exe/mammoth validate config/mammoth.example.yml
5. Bootstrap operational state
mammoth bootstrap config/mammoth.yml
This creates the SQLite database and initializes operational tables.
6. Start Mammoth
mammoth start config/mammoth.yml
Mammoth runs in the foreground until the process is terminated by your shell, process manager, Docker, Docker Compose, or Kubernetes.
7. Insert a row
INSERT INTO orders (status, total_cents)
VALUES ('created', 8888);
Expected flow:
INSERT
↓
PostgreSQL logical replication
↓
Mammoth
↓
Webhook POST
See Webhook Payloads for the canonical event and transaction JSON shapes, column-change availability, and destination idempotency guidance.
8. Inspect status
mammoth status config/mammoth.yml
This reports operational state from the SQLite database.
Before production
- Run
mammoth observability CONFIGand alert on slot readiness, invalidation, retained WAL, and safe WAL size. - Monitor PostgreSQL disk capacity and catalog-XID age with infrastructure tooling.
- Use a permanent, DBA-managed slot after bootstrap and recover the slot and Mammoth operational state as one continuity boundary.
- Coordinate schema migrations with webhook consumers; DDL and sequence state are not replicated.
- Require destination-side idempotency and use Mammoth's dead-letter workflow for failed or conflicting deliveries.