Skip to main content
Tinybird is our real-time analytics backend. All usage events flow through a single ingestion point and are materialized into purpose-specific views for querying.

Datasources

Primary source

events_by_ingested_at is the single ingestion point. All events are written here from Python via ingest_events() in server/polar/integrations/tinybird/service.py.

Materialized views

All datasources (materialized views and regular tables) live in tinybird/datasources. The materialization pipes in tinybird/pipes define how the views are built.

Lineage

Visual lineage: Tinybird Production Lineage

Adding a column

  1. Add the column to datasources/events_by_ingested_at.datasource
  2. Map the field in TinybirdEvent in server/polar/integrations/tinybird/service.py (the _event_to_tinybird function) — fields are extracted from user_metadata via .pop() so they’re denormalized into columns
  3. Add it to any materialized view datasources that need it (e.g. events_by_timestamp.datasource, system_events_by_org.datasource)
  4. Update the corresponding materialization pipes to SELECT the new column

Local development

CI runs tb fmt --diff, tb build, and tb test run on any changes to server/tinybird/**.

Deploying changes

Same process with production credentials. Switch workspaces using tb --cloud workspace ls and tb --cloud workspace use <name>. Tinybird performs a migration of historical data on deploy. If a column change requires backfilling, add a Forward Query. Deploys with backfills can take >45 minutes depending on data volume.

Ingestion errors and reconciliation

If events have failed to ingest, use the reconcile script to find and re-ingest missing events:
The script compares event IDs between PostgreSQL and the events_by_ingested_at datasource in the given time range, then re-ingests any missing events. Tinybird has a slight latency from PostgreSQL, so if your end timestamp is close to the current time, it will always report a mismatch. Running it with those events will generate duplicates.

Other scripts

  • Full backfill: uv run python -m scripts.backfill_tinybird_events --batch-size 5000 --start-date <iso8601> --cutoff-date <iso8601>
  • Cleanup/reingest specific events: uv run python -m scripts.tinybird_events_cleanup events.json --delete --reingest