Databases

Send events to PostgreSQL

Row-shaped event delivery into a customer-owned Postgres table, UPSERT by primary key, idempotent.

What is PostgreSQL?

PostgreSQL is the open-source relational database used by most modern application stacks. As a destination, Postgres works when the customer wants events in the same database their operational app uses, for joins against their domain tables, in-app analytics, or audit trails. Pushrail's adapter writes one row per event with the canonical envelope columns plus the payload as JSONB.

Why deliver events to PostgreSQL

  • Same database as the customer's application, joins are trivial.
  • JSONB stores arbitrary payloads with index support.
  • In-app analytics queries run against the same connection pool the app already has.
  • Audit-trail use cases benefit from transactional guarantees.

How Pushrail delivers events to PostgreSQL

The adapter writes one row per event using `INSERT … ON CONFLICT (event_id) DO NOTHING` so re-runs are naturally idempotent. The table shape is the canonical envelope: `event_id` (UUID PK), `event_type` (TEXT), `occurred_at` (TIMESTAMPTZ), `customer_external_id` (TEXT), `source` (TEXT), `payload` (JSONB), `metadata` (JSONB), `received_at` (TIMESTAMPTZ DEFAULT now()). Customers can opt into one table per event type for tighter schemas, or stay with the single-table default.

Auth and credentials

Username/password over TLS (default) or AWS IAM authentication for RDS-hosted Postgres (recommended, short-lived tokens, no static passwords). Credentials encrypted at rest. The customer creates a dedicated `pushrail_writer` role with `INSERT` on the destination table and no other privileges.

Batching, retries, and replay

Inserts are batched in groups of 1,000 events per transaction with a 1-second flush window. Transient errors (connection reset, deadlock) retry with exponential backoff. Permanent errors (auth, table not found) land in the DLQ. The `ON CONFLICT` clause makes replays a true no-op on already-inserted rows; the customer never sees duplicates.

Example payload

Pushrail accepts the canonical event shape on POST /v1/events. Below is the ingestion request your service makes.

{
  "eventType": "order.completed",
  "occurredAt": "2026-05-26T14:21:08.493Z",
  "source": "billing-service",
  "customerExternalId": "acct_8K2zRq",
  "idempotencyKey": "order_38a91f-completed",
  "correlationId": "req_4f30b2",
  "payload": {
    "orderId": "ord_38a91f",
    "amount": 12900,
    "currency": "USD",
    "items": [
      { "sku": "PR-PRO-MONTHLY", "qty": 1, "price": 12900 }
    ]
  },
  "metadata": {
    "tier": "pro",
    "region": "us-east-1"
  }
}

Example configuration

The fields your customer fills in to point Pushrail at their PostgreSQL setup.

{
  "type": "POSTGRES",
  "name": "Customer Postgres",
  "host": "acme-prod.cluster-abc123.us-east-1.rds.amazonaws.com",
  "port": 5432,
  "database": "acme_app",
  "schema": "pushrail",
  "table": "events",
  "tls": true,
  "auth": {
    "mode": "RDS_IAM",
    "username": "pushrail_writer",
    "region": "us-east-1"
  },
  "batchSize": 1000,
  "flushIntervalSec": 1
}

Common use cases

  • Land events in the same database the customer's app already uses for trivial joins.
  • Power an in-app analytics tab over event history without a separate warehouse.
  • Audit log destinations with transactional guarantees.
  • Per-customer audit tables for compliance evidence.

Frequently asked questions

How does Pushrail write events into Postgres?

One row per event using INSERT … ON CONFLICT (event_id) DO NOTHING, so re-runs are naturally idempotent. The table uses the canonical envelope columns plus payload and metadata as JSONB. Customers can keep the single-table default or opt into one table per event type.

Why land events in Postgres instead of a warehouse?

When the customer wants events in the same database their operational app uses, for trivial joins against domain tables, in-app analytics over the existing connection pool, or audit trails with transactional guarantees.

Whose credentials are used and how is it secured?

The customer's. They create a dedicated pushrail_writer role with INSERT on the destination table and no other privileges. Pushrail connects with username/password over TLS or AWS IAM authentication for RDS-hosted Postgres (recommended, short-lived tokens). Credentials are encrypted at rest.

Are replays safe?

Yes. Inserts are batched in groups of 1,000 per transaction. Transient errors (connection reset, deadlock) retry with backoff; permanent errors (auth, missing table) land in the dead-letter queue. The ON CONFLICT clause makes replay a true no-op on already-inserted rows, so the customer never sees duplicates.

Send events to PostgreSQL

Sandbox is open. No credit card.