Skip to content

Debezium Server to send changes directly to Tinybird Events API

Notifications You must be signed in to change notification settings

tinybirdco/kafkaless-cdc

Repository files navigation

PostgreSQL CDC to Tinybird with Debezium

Stream database changes from PostgreSQL to Tinybird in real-time using Debezium Server. This demo shows how to capture inserts, updates, and deletes via Change Data Capture (CDC) and send them to Tinybird's Events API.

Architecture

PostgreSQL (logical replication)
    ↓ 
Debezium Server (CDC capture & transform)
    ↓
HTTP POST to Tinybird Events API
    ↓
Tinybird Data Source (cdc_raw)

Key Components:

  • PostgreSQL 16: Source database with logical replication enabled
  • Debezium Server 3.1: Captures changes and transforms them
  • Tinybird: Real-time analytics platform (cloud for production and local for development)

Local Development (Tinybird Local)

Run the entire stack locally with Tinybird Local for development and testing.

Prerequisites

  • Docker (or OrbStack) and Docker Compose
  • Tinybird CLI: curl https://www.tinybird.co/download/cli | sh
  • Tinybird Local: tb local start in your terminal after installing the Tinybird CLI

Step-by-Step Guide

Step 1: Start infrastructure (Postgres + Tinybird)

docker-compose -f docker-compose-tblocal.yml --env-file .env.local up -d

This starts only PostgreSQL and Tinybird. Debezium stays stopped (it's in the cdc profile) because you need to first deploy the Tinybird project, get the append token, and pass it to the Debezium configuration.

Step2: Authenticate with Tinybird CLI

tb login

Follow the prompts to authenticate with Tinybird.

Step 3: Deploy the Tinybird project

tb deploy

This creates the cdc_raw Data Source and generates a scoped debezium_write token with append-only permissions.

Step 5: Copy the token

tb token copy debezium_write

This copies the token to your clipboard.

Step 6: Update .env.local with the token

Open .env.local and update the TINYBIRD_TOKEN value with the token from your clipboard:

TINYBIRD_TOKEN=<paste-the-token-here>
TINYBIRD_HOST=tinybird:7181

Step 7: Start the CDC pipeline (Debezium)

docker-compose -f docker-compose-tblocal.yml --env-file .env.local --profile cdc up -d

Now Debezium starts and begins capturing changes from PostgreSQL.

Step 8: Test the pipeline

# Connect to PostgreSQL
docker exec -it postgres-cdc-source psql -U postgres -d inventory
-- Insert a new customer
INSERT INTO customers (first_name, last_name, email)
VALUES ('Test', 'User', 'test@example.com');

-- Update a customer
UPDATE customers SET first_name = 'Updated' WHERE email = 'test@example.com';

-- Delete a customer
DELETE FROM customers WHERE email = 'test@example.com';

Step 9: Verify events in Tinybird

tb sql "SELECT fromUnixTimestamp64Milli(JSONExtractInt(payload,'__source_ts_ms')) __source_ts_ms, * FROM cdc_raw ORDER BY __source_ts_ms"

Or type tb open and go to https://cloud.tinybird.co/local/7181/<your-workspace>/datasources/cdc_raw to see them inthe Tinybird Local UI.

Step 10: Monitor Debezium

docker-compose -f docker-compose-tblocal.yml --env-file .env.local logs -f debezium-server

Production Deployment (Tinybird Cloud)

  1. Deploy the project to Tinybird Cloud with tb --cloud deploy.
  2. Get your host from tb --output=json info | jq -r ".cloud.api" and copy the token from tb --cloud token copy debezium_write.
  3. Use these credentials to update your .env file for Debezium
  4. Make the needed changes so that Debezium reads from your Postgres.

Understanding the Data

The cdc_raw Data Source receives events with this structure:

{
  "id": 1,
  "first_name": "John",
  "last_name": "Doe",
  "email": "john.doe@example.com",
  "created_at": 1767959534139174,
  "updated_at": 1767959534139174,
  "__deleted": "false",
  "__op": "c",
  "__table": "customers",
  "__source_ts_ms": 1767999538489
}

Operation codes:

  • c = CREATE (insert)
  • u = UPDATE
  • d = DELETE
  • r = READ (initial snapshot)

Stopping Services

# Stop all services (local)
docker-compose -f docker-compose-tblocal.yml --env-file .env.local --profile cdc down

Troubleshooting

Debezium crashed or won't start

Check the logs:

docker-compose -f docker-compose-tblocal.yml --env-file .env.local logs debezium-server

Common issues:

  • "Datasource cdc_raw not found": The Data Source wasn't deployed. Run tb deploy again.
  • "Invalid token": The token in .env.local doesn't match. Regenerate with tb token copy debezium_write.
  • Container exits immediately: Check if you started with --profile cdc flag.

Reset offsets (start from scratch)

docker-compose -f docker-compose-tblocal.yml --env-file .env.local down
rm -rf debezium-data/offsets.dat
docker-compose -f docker-compose-tblocal.yml --env-file .env.local up -d

View all container status

docker-compose -f docker-compose-tblocal.yml --env-file .env.local --profile cdc ps

How It Works

  1. PostgreSQL is configured with wal_level=logical to enable Change Data Capture
  2. Debezium Server connects to PostgreSQL and monitors the Write-Ahead Log (WAL)
  3. Changes are captured and transformed using ExtractNewRecordState to flatten the event structure
  4. Events are sent via HTTP POST to Tinybird's Events API endpoint
  5. Tinybird ingests the events into the cdc_raw Data Source in real-time

Files & Configuration

  • docker-compose-tblocal.yml - Local Tinybird setup with Docker Compose profiles
  • pg/init-db.sql - PostgreSQL initialization with sample tables
  • tinybird/cdc_raw.datasource - Tinybird Data Source definition
  • .env.local - Local environment variables
  • debezium-data/ - Offset tracking (auto-created)
  • docker-compose.yml - Local Postgres and Debezium pointing to Tinybird Cloud

Docker Compose Profiles

The local setup uses profiles for controlled startup:

  • Default profile: Postgres + Tinybird (start first)
  • cdc profile: Debezium (start after deploying Data Source)

This ensures the Data Source exists before Debezium tries to send events.

Learn More

Next steps

  • Improving the Tinybird project

  • Creating one Datasource per table with ReplacingMergeTree Engine.

  • Testing at a bigger scale

About

Debezium Server to send changes directly to Tinybird Events API

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published