Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sinks Overview

When you publish a message to a pg_tide outbox, that message sits safely in your PostgreSQL database, waiting to be delivered somewhere useful. A sink is the destination where the pg_tide relay delivers those messages. Think of it like a postal service: your application drops a letter (message) into a mailbox (outbox), and the postal carrier (relay) delivers it to the recipient's address (sink).

pg_tide supports 30 different sinks, covering everything from traditional message queues like Apache Kafka and RabbitMQ, to cloud services like Amazon SQS and Google Cloud Pub/Sub, to modern data lakes like Apache Iceberg and Delta Lake, to notification services like Slack and PagerDuty. No matter where your messages need to go, there is likely a sink that fits your needs.

Choosing the Right Sink

Selecting a sink depends on what you are trying to accomplish. The table below groups sinks by category and highlights the primary use case for each. If you are building a new system and have flexibility in choosing your messaging infrastructure, start with the category that matches your architectural goals, then read the detailed page for each sink to understand the trade-offs.

Message Queues & Streaming

These sinks deliver messages to traditional message brokers and streaming platforms. They are ideal when you need durable, ordered message delivery to multiple consumers, or when you are integrating with an existing event-driven architecture.

SinkBest ForOrderingDelivery Guarantee
Apache KafkaHigh-throughput streaming, event sourcing, CDC pipelinesPer-partitionAt-least-once (exactly-once with idempotent producer)
NATS JetStreamLow-latency pub/sub, microservice communicationPer-subjectAt-least-once (exactly-once with dedup)
RabbitMQComplex routing, work queues, legacy integrationPer-queueAt-least-once (with publisher confirms)
Redis StreamsLightweight streaming, real-time dashboardsPer-streamAt-least-once
Amazon SQSAWS-native queuing, serverless triggersFIFO optionalAt-least-once (exactly-once with FIFO)
Amazon KinesisReal-time analytics on AWS, high-volume ingestionPer-shardAt-least-once
Google Cloud Pub/SubGCP-native messaging, global distributionPer-ordering-keyAt-least-once
Azure Service BusEnterprise messaging on Azure, sessions, transactionsPer-sessionAt-least-once
Azure Event HubsHigh-throughput event ingestion on AzurePer-partitionAt-least-once
MQTT v5IoT device communication, edge computingPer-topic (QoS dependent)Configurable (QoS 0/1/2)

Analytics & Data Lakes

These sinks write messages directly into analytical databases and data lake storage. They are ideal when your PostgreSQL events need to feed dashboards, machine learning pipelines, or long-term analytical storage without going through an intermediate message broker.

SinkBest ForFormatBatch Support
ClickHouseReal-time analytics, time-series, log storageNative protocolYes (batch inserts)
SnowflakeCloud data warehouse, BI reportingStage + COPYYes (micro-batches)
BigQueryGoogle Cloud analytics, large-scale queriesStreaming/LoadYes (streaming inserts)
Apache IcebergOpen table format, lakehouse architectureParquetYes (append commits)
Delta LakeDatabricks ecosystem, ACID on object storageParquetYes (append commits)
DuckLakeLightweight lakehouse, PostgreSQL-cataloged ParquetParquetYes (batch writes)
MongoDBDocument storage, flexible schemasBSON documentsYes (bulk writes)
ElasticsearchFull-text search, log analytics, APMJSON documentsYes (bulk API)
Object StorageS3/GCS/Azure Blob archival, data lake landingJSONL or ParquetYes (file-per-batch)
Apache Arrow FlightHigh-performance columnar transfer, ML pipelinesArrow IPCYes (record batches)

Notifications & Webhooks

These sinks deliver messages to notification services and HTTP endpoints. They are ideal for alerting, triggering external workflows, and integrating with third-party APIs that expect HTTP callbacks.

SinkBest ForFormat
HTTP WebhookThird-party API integration, custom endpointsJSON POST
SlackTeam notifications, operational alertsBlock Kit messages
DiscordCommunity notifications, bot integrationsEmbed messages
PagerDutyIncident management, on-call alertingEvents API v2

Connector Ecosystems

These sinks integrate with established connector frameworks, giving you access to hundreds of additional destinations through a single configuration. Instead of pg_tide implementing a direct connection to every possible system, these adapters let you leverage existing connector ecosystems.

SinkBest ForEcosystem Size
Singer / MeltanoOpen-source ETL, Meltano Hub targets~500 targets
AirbyteManaged data integration, destination connectors~400 connectors
Fivetran HVREnterprise data integration, HVR endpointFivetran ecosystem

Infrastructure

These sinks deliver messages to other PostgreSQL instances or output streams. They are useful for database-to-database messaging, testing, and debugging.

SinkBest For
PostgreSQL InboxCross-service messaging within PostgreSQL
Remote PostgreSQL OutboxMulti-cluster federation
stdout / FileDebugging, log capture, piping to external tools

Common Configuration Patterns

Every sink is configured through the relay pipeline's JSONB configuration stored in PostgreSQL. The basic pattern looks like this:

SELECT tide.relay_set_outbox(
    'my-pipeline',
    'orders',
    'relay-group',
    '{
        "sink_type": "kafka",
        "brokers": "localhost:9092",
        "topic": "order-events"
    }'::jsonb
);

The sink_type field determines which sink implementation the relay uses. All other fields in the JSON object are sink-specific configuration. Every sink page documents its complete configuration reference.

Secret Management

Sensitive values like passwords, API keys, and connection strings should never be stored directly in the pipeline configuration. Instead, use secret interpolation:

{
    "sink_type": "kafka",
    "brokers": "${env:KAFKA_BROKERS}",
    "sasl_username": "${env:KAFKA_USERNAME}",
    "sasl_password": "${env:KAFKA_PASSWORD}"
}

The relay resolves ${env:VAR_NAME} tokens from environment variables and ${file:/path/to/secret} from files at startup. Resolved values are never written to logs or metric labels.

Delivery Guarantees

All sinks provide at-least-once delivery by default. The relay acknowledges messages in the outbox only after the sink confirms receipt. If the relay crashes between delivering a message and acknowledging it, the message will be delivered again on restart.

For sinks that support it, you can achieve exactly-once semantics by combining pg_tide's outbox deduplication key with the sink's native deduplication mechanism. Each sink page documents whether exactly-once is possible and how to configure it.

Error Handling

When a sink cannot accept a message (network failure, authentication error, malformed payload), the relay retries with exponential backoff. If retries are exhausted, the message is routed to the dead-letter queue (DLQ) for manual inspection and replay. The circuit breaker protects against cascading failures by temporarily halting delivery when a sink is consistently unavailable.

Next Steps

Browse the sink pages that match your use case, or start with the most common choices: