Skip to Content

Backend Environment Variables

Set these in docker-compose.yml under the backend service, or in a .env file.

VariableDefaultDescription
PORT3001Backend API port
DATABASE_URLPostgreSQL connection string (e.g., postgresql://tandemu:tandemu@postgres:5432/tandemu)
REDIS_URLRedis connection string (e.g., redis://redis:6379)
CLICKHOUSE_URLClickHouse HTTP URL (e.g., http://clickhouse:8123)
JWT_SECRETchange-me-in-productionSecret for signing JWT tokens. Change this in production.
CORS_ORIGINhttp://localhost:3000Allowed CORS origin for the frontend
STRIPE_SECRET_KEYStripe secret key (SaaS billing, optional)
STRIPE_WEBHOOK_SECRETStripe webhook signing secret (optional)

Frontend Environment Variables

VariableDefaultDescription
NEXT_PUBLIC_API_URLhttp://localhost:3001Backend API URL (accessed from the browser)

OTel Collector Configuration

The collector config is at otel-collector.yaml in the repo root. It defines:

Receivers:

  • OTLP gRPC on port 4317
  • OTLP HTTP on port 4318

Processors:

  • memory_limiter — Prevents OOM (512 MiB limit)
  • batch — Batches 10,000 records or 5s, whichever comes first

Exporters:

  • clickhouse — Writes to ClickHouse with auto-schema creation
  • debug — Logs basic info (useful for troubleshooting)

To modify the pipeline, edit otel-collector.yaml and restart the collector:

docker compose restart otel-collector

Database

PostgreSQL Schema

Tables are created by migration scripts in packages/database/src/migrations/:

MigrationCreates
0001_initial.sqlorganizations, users, memberships tables + RLS policies
0002_teams_and_invites.sqlteams, team_members, invites tables + RLS
0003_integrations.sqlintegrations, integration_project_mappings tables + RLS

All tables use Row-Level Security (RLS) for tenant isolation. Every query is scoped to the current organization via SET LOCAL app.current_tenant.

ClickHouse Tables

Created automatically by the OTel Collector on first startup:

TableData
otel_tracesSession spans, deployment events
otel_metrics_sumCode line counters (AI vs manual)
otel_logsFriction events (prompt loops, errors)

Data has a 90-day TTL by default.

Applying Migrations

Migrations are idempotent (safe to run multiple times):

docker exec -i tandemu-postgres-1 psql -U tandemu -d tandemu < packages/database/src/migrations/0001_initial.sql docker exec -i tandemu-postgres-1 psql -U tandemu -d tandemu < packages/database/src/migrations/0002_teams_and_invites.sql docker exec -i tandemu-postgres-1 psql -U tandemu -d tandemu < packages/database/src/migrations/0003_integrations.sql

Security Notes

  • Change JWT_SECRET in production — the default is not secure
  • API tokens for integrations are stored in PostgreSQL — consider encrypting at rest in production
  • RLS ensures organization data isolation at the database level
  • CORS is restricted to the configured origin
  • Stripe webhooks use cryptographic signature verification
Last updated on