{
  "record": {
    "id": 1234,
    "customer_id": 789,
    "product": "Wireless Headphones",
    "quantity": 1,
    "price": 199.99,
    "status": "pending",
    "created_at": "2024-10-28T21:37:01.127470Z",
    "updated_at": "2024-10-28T21:37:01.127470Z"
  },
  "changes": null,
  "action": "insert",
  "metadata": {
    "table_schema": "public",
    "table_name": "orders",
    "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
    "commit_timestamp": "2024-10-28T21:37:01.127470Z",
    "commit_lsn": 123456789,
    "commit_idx": 1,
    "database_name": "myapp-prod", // deprecated
    "consumer": {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "name": "orders_kafka",
      "annotations": {"my-custom-key": "my-custom-value"}
    },
    "database": {
      "id": "12345678-9abc-def0-1234-56789abcdef0",
      "name": "myapp-prod",
      "annotations": {"my-custom-key": "my-custom-value"},
      "database": "myapp-prod",
      "hostname": "db.example.com"
    },
    "transaction_annotations": {
      "username": "paul.atreides",
      "source": "web_ui",
      "request_id": "req_123"
    }
  }
}

Sequin converts Postgres changes into JSON messages that are delivered to your sinks. Each message contains the current record, any previous values, the action that occurred, and metadata about the event.

You can apply a transform to the message to modify the data before it is delivered to your sink.

{
  "record": {
    "id": 1234,
    "customer_id": 789,
    "product": "Wireless Headphones",
    "quantity": 1,
    "price": 199.99,
    "status": "pending",
    "created_at": "2024-10-28T21:37:01.127470Z",
    "updated_at": "2024-10-28T21:37:01.127470Z"
  },
  "changes": null,
  "action": "insert",
  "metadata": {
    "table_schema": "public",
    "table_name": "orders",
    "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
    "commit_timestamp": "2024-10-28T21:37:01.127470Z",
    "commit_lsn": 123456789,
    "commit_idx": 1,
    "database_name": "myapp-prod", // deprecated
    "consumer": {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "name": "orders_kafka",
      "annotations": {"my-custom-key": "my-custom-value"}
    },
    "database": {
      "id": "12345678-9abc-def0-1234-56789abcdef0",
      "name": "myapp-prod",
      "annotations": {"my-custom-key": "my-custom-value"},
      "database": "myapp-prod",
      "hostname": "db.example.com"
    },
    "transaction_annotations": {
      "username": "paul.atreides",
      "source": "web_ui",
      "request_id": "req_123"
    }
  }
}
record
object

The current state of the row. Contains all column values.

changes
object

For update operations, contains the previous values of changed fields. For insert and delete operations, this field is null.

action
string

The type of change that occurred. One of:

  • insert: A new row was created
  • update: An existing row was modified
  • delete: A row was deleted
  • read: A row was read during a backfill
metadata
object

Additional context about the change.

Idempotency

The metadata of each message includes an idempotency_key which your application can use to reject any possible duplicate messages.

For regular changes (non-backfill), the idempotency key is based on the transaction’s position in the database log and its position within that transaction.

For backfill messages, the key is based on the backfill’s unique identifier and the primary key values of the record being processed.