Table Schema
The outbox_events table is the heart of the Transactional Outbox pattern.
It is designed to be highly performant for concurrent polling relays while keeping a strict audit trail of every event.
outbox_events Schema Reference
| Column | Type | Purpose |
|---|---|---|
id |
BIGSERIAL |
Sequential Primary Key. Ensures new rows are appended to the end of the table, avoiding B-tree index fragmentation. |
event_id |
UUID |
Business ID of the event. It is automatically mapped to the Nats-Msg-Id header to enable JetStream deduplication. This ID remains stable across retries. |
subject |
TEXT |
The NATS JetStream subject where this event will be published (e.g. order.created). |
headers |
JSONB |
Optional NATS headers. The relay will always automatically inject Nats-Msg-Id here. |
payload |
JSONB |
The body of the event. |
status |
TEXT |
Tracks the lifecycle. Valid values are pending, published, or failed. |
retry_count |
SMALLINT |
Number of failed publish attempts. Used to trigger dead-lettering after OUTBOX_MAX_RETRIES. |
last_error |
TEXT |
Stores the last exception traceback for debugging purposes if a publish fails. |
aggregate_id |
TEXT |
The ID of the source entity (e.g., the Order ID). Used for ordering and observability. |
aggregate_type |
TEXT |
The class name of the source entity (e.g., Order). |
created_at |
TIMESTAMPTZ |
When the event was initially written to the outbox. |
updated_at |
TIMESTAMPTZ |
Timestamp of the last relay modification. Kept accurate via a Postgres Trigger. |
scheduled_at |
TIMESTAMPTZ |
The earliest time this event is allowed to be published. Exponential backoff pushes this forward on failures. |
published_at |
TIMESTAMPTZ |
The exact time a successful JetStream ACK was received. |
Why use event_id and not id for NATS?
The id is a sequential integer (BIGSERIAL). While useful for database performance, it is specific to the database sequence state.
The event_id is a UUIDv4 generated by the application at the exact moment the event is staged. By mapping this UUID to the Nats-Msg-Id header, NATS JetStream can perform strictly deterministic deduplication, even if the database sequence was reset or if the event was re-imported from a backup.