This document describes the internal architecture of the Tinybird TypeScript SDK.
The SDK is organized into layers that handle different responsibilities:
┌─────────────────────────────────────────────────────────────┐
│ User Code │
│ defineDatasource, definePipe, defineKafkaConnection, etc. │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Schema Layer │
│ TypeScript definitions with branded types │
│ src/schema/ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Generator Layer │
│ Converts definitions to Tinybird datafile format content │
│ src/generator/ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API Layer │
│ Sends generated content to Tinybird API │
│ src/api/ │
└─────────────────────────────────────────────────────────────┘
Provides TypeScript-first schema definitions with branded types for type safety.
Files:
types.ts- Column type validators (t.string(),t.dateTime(), etc.)params.ts- Parameter validators for pipes (p.string(),p.int32(), etc.)engines.ts- Table engine configurations (engine.mergeTree(), etc.)datasource.ts-defineDatasource()for table definitionspipe.ts-definePipe(),defineEndpoint(),defineMaterializedView(),defineCopyPipe()connection.ts-defineKafkaConnection()for external connectionsproject.ts-defineProject()to aggregate all resources
Key Patterns:
- Branded types using Symbols (
DATASOURCE_BRAND,PIPE_BRAND,CONNECTION_BRAND) - Type guards for runtime checks (
isDatasourceDefinition(),isPipeDefinition()) - Full TypeScript inference for row types, params, and outputs
Converts in-memory definitions to Tinybird datafile format content strings.
Files:
datasource.ts- Generates.datasourcefile contentpipe.ts- Generates.pipefile contentconnection.ts- Generates.connectionfile contentloader.ts- Loads and bundles TypeScript schema files using esbuildindex.ts- Orchestrates building all resourcesclient.ts- Generates typed client code
Key Concepts:
- Generated content is stored in memory, not written to disk
- Each generator returns
{ name: string, content: string } - Content follows Tinybird's datafile format (KEY VALUE pairs)
Example generated .datasource content:
DESCRIPTION >
Event tracking data
SCHEMA >
timestamp DateTime `json:$.timestamp`,
event_type String `json:$.event_type`
ENGINE "MergeTree"
ENGINE_SORTING_KEY "timestamp"
Sends generated resources to Tinybird's API and fetches existing resources.
Files:
build.ts-buildToTinybird()deploys resources to branches via/v1/builddeploy.ts-deployToMain()deploys resources to main workspace via/v1/deploybranches.ts- Branch management APIworkspaces.ts- Workspace discoveryresources.ts- Fetch existing datasources and pipes from workspacelocal.ts- Local Tinybird container integrationapi.ts- Public decoupled API wrapper (createTinybirdApi())
Key Patterns:
- Resources sent as multipart form data
- File extensions indicate resource type (
.datasource,.pipe,.connection) - Form field
data_project://signals Tinybird to process the file /v1/buildfor branches,/v1/deployfor main workspace- Public API wrapper can be used standalone with only
baseUrl+token - Public API exposes direct runtime methods:
query(),ingest(),sql()
Converts Tinybird API responses to TypeScript SDK code.
Files:
index.ts- Main code generators (generateDatasourceCode(),generatePipeCode(), etc.)type-mapper.ts- Maps ClickHouse types tot.*validatorsutils.ts- Helpers for case conversion, escaping, engine code generation
Key Patterns:
- Maps ClickHouse types (String, DateTime, Nullable, LowCardinality, etc.) to SDK validators
- Generates proper import statements based on used types
- Handles all pipe types: endpoint, materialized, copy, regular
User-facing commands for development workflow.
Commands:
tinybird init- Initialize a new project (detects existing.datasource/.pipefiles)tinybird dev- Watch mode with hot reload (feature branches only)tinybird build- Build and deploy to branches (not main)tinybird deploy- Deploy to main workspace (production)tinybird login- Authenticate with Tinybirdtinybird branch- Branch management (list, status, delete)
Key Files:
index.ts- Command definitions and entry pointcommands/init.ts- Project initialization with datafile detectioncommands/build.ts- Build to branchescommands/deploy.ts- Deploy to maincommands/dev.ts- Watch modecommands/login.ts- Authenticationcommands/branch.ts- Branch managementconfig.ts- Configuration file managementenv.ts- Environment variable loadinggit.ts- Git integration for branch detection
Safety Features:
buildanddevcommands are blocked on main branch in cloud mode- Only
deploycommand can push to production - Prevents accidental production deployments during development
Runtime client for querying and ingesting data.
Files:
base.ts-TinybirdClientclass with query/ingest methodstypes.ts- Response types and error handling
Usage:
const client = createClient({
baseUrl: 'https://api.tinybird.co',
token: 'p.xxx',
});
// Query a pipe
const result = await client.query('top_events', { limit: 10 });
// Ingest data
await client.ingest('events', { timestamp: new Date(), event_type: 'click' });Utility types for inferring TypeScript types from schema definitions.
Key Types:
InferRow<T>- Infer the row type of a datasourceInferParams<T>- Infer the params type of a pipeInferOutputRow<T>- Infer the output row type of a pipe
1. User defines schema in TypeScript
│
▼
2. loadSchema() bundles with esbuild and executes
│
▼
3. generateResources() converts to datafile content
│
▼
4. buildToTinybird() sends as multipart form to API
│
▼
5. Tinybird API processes and creates resources
1. Load schema files
│
▼
2. Generate resources
│
▼
3. Deploy to Tinybird (dev branch)
│
▼
4. Watch for file changes ─────────┐
│ │
▼ │
5. On change, reload and redeploy ─┘
Kafka connections are defined with defineKafkaConnection() and referenced in datasources:
// Define connection
const myKafka = defineKafkaConnection('my_kafka', {
bootstrapServers: 'kafka.example.com:9092',
securityProtocol: 'SASL_SSL',
saslMechanism: 'PLAIN',
key: '{{ tb_secret("KAFKA_KEY") }}',
secret: '{{ tb_secret("KAFKA_SECRET") }}',
});
// Reference in datasource
const kafkaEvents = defineDatasource('kafka_events', {
schema: { /* ... */ },
kafka: {
connection: myKafka,
topic: 'events',
groupId: 'my-consumer-group',
autoOffsetReset: 'earliest',
},
});Generated .connection content:
TYPE kafka
KAFKA_BOOTSTRAP_SERVERS kafka.example.com:9092
KAFKA_SECURITY_PROTOCOL SASL_SSL
KAFKA_SASL_MECHANISM PLAIN
KAFKA_KEY {{ tb_secret("KAFKA_KEY") }}
KAFKA_SECRET {{ tb_secret("KAFKA_SECRET") }}
Generated .datasource content includes:
KAFKA_CONNECTION_NAME my_kafka
KAFKA_TOPIC events
KAFKA_GROUP_ID my-consumer-group
KAFKA_AUTO_OFFSET_RESET earliest
Tests are colocated with source files (*.test.ts).
Run all tests:
pnpm testRun tests in watch mode:
pnpm test --watch