Destination type
PostgreSQL Destination Configuration
Use PostgreSQL destinations to insert every routed event directly into an existing PostgreSQL table for operational data, audit streams, analytics staging, or database-driven workflows. This destination configuration reference covers the fields and delivery behavior required to connect it to FastHook.
For PostgreSQL destinations, FastHook opens a short-lived database connection, performs one parameterized INSERT, closes the connection, and stores the result as delivery attempt evidence.
PostgreSQL dashboard fields
Host, port, and databaseThe public PostgreSQL endpoint and database name.
Username and passwordCredentials for a role that can insert into only the target table.
TLS modeCertificate verification is enabled by default.
Schema and tableExisting destination table. FastHook does not create or migrate it.
Column mappingPayload JSONB plus optional event ID, metadata JSONB, and delivered-at columns.
Duplicate event behaviorFail duplicates or ignore them using a unique event ID column.
PostgreSQL API config
config.host / config.portPublicly reachable PostgreSQL host and TCP port. Port defaults to 5432.
config.databaseDatabase that contains the destination table.
config.schema / config.tableTarget schema and table. Schema defaults to public.
config.payload_columnRequired JSONB column that receives the routed payload. Defaults to payload.
config.event_id_columnOptional text column for FastHook event IDs and idempotent redelivery handling.
config.metadata_columnOptional JSONB column for request, source, connection, and delivery metadata.
config.delivered_at_columnOptional timestamptz column for the insertion time.
config.on_conflictERROR or IGNORE. IGNORE requires event_id_column and a matching unique constraint.
config.ssl_modeverify-full (default) or disable. Cloudflare Workers does not expose a TLS-without-verification mode for PostgreSQL sockets.
config.connect_timeout_secondsConnection and authentication timeout from 1 to 30 seconds. Defaults to 10.
config.authusername and password for a least-privilege PostgreSQL writer role.
config.rate_limitDelivery pacing. New PostgreSQL destinations default to 5 inserts per second.
{
"name": "postgres-event-store",
"type": "POSTGRESQL",
"config": {
"host": "db.example.com",
"port": 5432,
"database": "events",
"schema": "public",
"table": "webhook_events",
"ssl_mode": "verify-full",
"payload_column": "payload",
"event_id_column": "event_id",
"metadata_column": "metadata",
"delivered_at_column": "delivered_at",
"on_conflict": "IGNORE",
"connect_timeout_seconds": 10,
"auth_type": "POSTGRES_PASSWORD",
"auth": {
"username": "fasthook_writer",
"password": "replace-with-a-secret"
},
"rate_limit": 5,
"rate_limit_period": "second"
}
}Create the table and writer role
Run this once as a database administrator, replace the example password, and store that writer password in the destination. FastHook never creates or migrates the target table.
CREATE TABLE public.webhook_events (
event_id text PRIMARY KEY,
payload jsonb NOT NULL,
metadata jsonb,
delivered_at timestamptz NOT NULL DEFAULT now()
);
CREATE ROLE fasthook_writer LOGIN PASSWORD 'replace-with-a-secret';
GRANT CONNECT ON DATABASE events TO fasthook_writer;
GRANT USAGE ON SCHEMA public TO fasthook_writer;
GRANT INSERT ON TABLE public.webhook_events TO fasthook_writer;If you use a different event ID column, keep a UNIQUE or primary-key constraint on that column before setting on_conflict to IGNORE.
PostgreSQL authentication
- PostgreSQL username and password
- TLS certificate verification
PostgreSQL delivery method and limit
Rate limit: Defaults to 5 inserts/second. Configure a lower or higher destination rate for your database capacity.
PostgreSQL delivery behavior
- FastHook performs one parameterized INSERT per delivery. Payload and metadata values never become SQL syntax.
- The payload column must be JSONB. Non-JSON source bodies are stored as a JSON string, so every delivery still produces valid JSONB.
- FastHook opens a short-lived connection inside the send Worker and closes it after the insert. The PostgreSQL driver is loaded only for PostgreSQL deliveries.
- The target must be publicly reachable. Cloudflare Workers block localhost and private-network addresses for ordinary outbound TCP sockets.
- FastHook does not create tables, columns, indexes, or constraints. Apply the documented DDL before enabling the connection.
- Delivery is at least once. Use event_id_column, a UNIQUE constraint, and on_conflict=IGNORE when side effects must be idempotent.
PostgreSQL setup checklist
- Create the destination table and a least-privilege writer role in PostgreSQL.
- Allow inbound PostgreSQL traffic from public networks according to your database provider's networking controls. Workers outbound TCP does not use a fixed single IP.
- Create a FastHook destination and choose POSTGRESQL.
- Enter host, port, database, credentials, TLS mode, schema, table, and column names.
- For idempotency, configure an event ID column with a UNIQUE constraint and choose Ignore by Event ID.
- Connect a source, send a test event, and inspect the attempt before routing production traffic.
PostgreSQL troubleshooting
Connection times out or the address is rejected.Use a public hostname, allow the database port in provider firewall controls, and confirm the database accepts public TCP connections. Localhost and private IP addresses are blocked by Cloudflare Workers.
TLS or certificate verification fails.Use verify-full with a publicly trusted certificate whose hostname matches config.host. Use disable only for an endpoint where unencrypted database traffic is explicitly acceptable.
Insert fails with permission denied or relation does not exist.Confirm database, schema, and table names and grant the writer role CONNECT, USAGE on the schema, and INSERT on the table.
Duplicate deliveries create duplicate rows.Add a UNIQUE constraint to the event ID column, set event_id_column, and use on_conflict=IGNORE.
Insert fails because a column has the wrong type.Use JSONB for payload and metadata, text for event ID, and timestamptz for delivered_at.