# Tinybird

> Hosted-ClickHouse AnalyticsSink over Tinybird's Events API + Pipes — pay-as-you-go OLAP without operating a cluster.



---

<!-- source: en/plugins/tinybird.md -->
## Tinybird

_Hosted-ClickHouse AnalyticsSink over Tinybird's Events API + Pipes — pay-as-you-go OLAP without operating a cluster._

`@voltro/plugin-tinybird` is the hosted-ClickHouse `AnalyticsSink` — it ingests
via Tinybird's **Events API** and reads via **Pipes** (saved SQL endpoints), so
you get ClickHouse-grade OLAP on a pay-as-you-go service instead of operating a
cluster yourself. It's for teams that ALREADY have a Tinybird workspace; if you
want a zero-setup external OLAP sink that owns its own schema, use
[`@voltro/plugin-clickhouse`](/docs/plugins/clickhouse) instead. For the shared
`AnalyticsSink` API and the `useAnalytics()` read methods, see
[Analytics & warehouse sinks](/docs/plugins/analytics).

## Install

```
pnpm add @voltro/plugin-tinybird
```

## Wiring

```ts
// app.config.ts
import { tinybirdAnalytics } from '@voltro/plugin-tinybird'

export default {
  type:      'api' as const,
  name:      'myApi',
  store:     'postgres' as const,
  analytics: tinybirdAnalytics({
    token:      process.env.TINYBIRD_TOKEN!,
    region:     'eu',                 // 'eu' | 'us-east' | 'us-west' | 'asia-southeast'
    datasource: 'voltro_events',
  }),
}
```

`track()` POSTs events to the Datasource via the Events API; `aggregate` /
`timeseries` / `topN` call your Pipes. There's no boot-time initialize — the
Datasource is auto-created on the first event, and the Pipes must already exist.
The trade-off is **deferred failure**: a bad token or missing Pipe boots clean
and surfaces as a typed `AnalyticsError` on the first call.

## Required Pipes

The plugin EXPECTS three canonical Pipes to exist in your workspace (create them
once via the `tb` CLI or the UI). It does NOT synthesize them — Tinybird's
`.pipe` DSL is too rich to generate from a generic spec:

- `events_aggregate` — params: `event`, `from`, `to`, `metric_expr`, `filter_sql`
- `events_timeseries` — same + `bucket_fn`
- `events_topn` — same + `group_expr`, `limit`

## Options

`tinybirdAnalytics(options)`:

| Option | Type | Default | Notes |
|---|---|---|---|
| `token` | `string` | — (**required**) | Tinybird workspace token. |
| `region` | `string` | `'eu'` | `'eu'` / `'us-east'` / `'us-west'` / `'asia-southeast'`. Selects the API base URL. |
| `apiUrl` | `string` | derived from `region` | Custom API base URL — overrides `region` (self-hosted Tinybird or preview envs). |
| `datasource` | `string` | `'voltro_events'` | The plugin POSTs events to `/v0/events?name=<datasource>`. |
| `pipes` | `{ aggregate?, timeseries?, topN? }` | the three canonical names | Override Pipe names if your team uses a different convention. |

`datasource` + the Pipe names are validated as identifiers at boot (they're
interpolated into request URLs), so a path-traversal name fails loudly rather
than building a bad URL.

> **Connection details come from `options`, not env.** The plugin reads no
> `TINYBIRD_*` variables itself — the example wires `process.env` into the
> options. Use `@voltro/env`'s `defineEnv` to declare the token as a secret.

## Provider escape hatch

For direct Pipe access beyond the cross-provider contract, import the `Tinybird`
Tag and `yield*` it for the configured client. Using the Tag binds your handler
to Tinybird — stay on `useAnalytics()` for provider-portable code.

## See also

- [Analytics & warehouse sinks](/docs/plugins/analytics) — the shared
  `AnalyticsSink` contract, the `useAnalytics()` read API, and `composeAnalytics`.
