Upgrading
Keep your self-hosted Yavio deployment up to date
Pulling Latest Images
The simplest way to upgrade is via the Yavio CLI:
npx @yavio/cli updateThis pulls the latest Yavio images (dashboard, ingest, docs) and restarts the services. Data volumes are preserved.
To also update third-party images (PostgreSQL, ClickHouse):
npx @yavio/cli update --allManual Upgrade
If you prefer using Docker Compose directly:
docker compose pull
docker compose up -dUpgrade the server before the SDK
Upgrade your self-hosted Yavio before you bump @yavio/sdk in your apps. A newer SDK can send values an older ingest service does not know yet, and ingest rejects such events one by one. The SDK never surfaces delivery errors, so they are lost silently.
@yavio/sdk 0.4.0 reports tool results with isError: true as error_category: "tool_error". An ingest image from before that release rejects every one of those events — so on an old server, tool-reported failures disappear instead of being counted. It also sends intent_context on tool calls, which an older ingest silently drops, so the dashboard's coverage split stays empty. Pull the latest images first, then upgrade the SDK.
@yavio/sdk 0.4.1 sends region (state or province) on tool calls with capture.geo true or "region". An ingest image from before migration 0020 drops the field silently; the event itself is stored.
@yavio/sdk 0.5.4 sends session_source (how the event's session was derived) on every server event. Migration 0022 adds the column; the migrate service applies it before ingest and the dashboard start. An ingest image from before it drops the field silently and stores the events, so the dashboard keeps counting one-call sessions of key-less clients as sessions until the server is upgraded.
Checking for Updates
Preview what would be pulled without making changes:
npx @yavio/cli update --dry-runDatabase Migrations
Database migrations run automatically when services start. Both PostgreSQL (via Drizzle) and ClickHouse migrations are applied on boot.
There is no manual migration step required. Just pull the latest images and restart.
Version Notes
Sessions of clients without a session key (migration 0022)
Migration 0022 adds session_source to events. From this release on, a session the SDK labels per_request — an HTTP call that carries no session key, on any host (SDK 0.5.4 and later; one call per "session" since 0.5.5, while 0.5.4 put all key-less callers of a server that reuses one stateless transport into one) — is no longer counted as a session: the Sessions KPI and the users list leave it out (the KPI says how many such calls there were), and the anonymous statistics count such an event as a person only through its user key and leave its connection rows out of the session cells. Older rows have no session_source and count as before. The statistics job recomputes the current and the previous month on its first run, so a figure in the anonymous statistics that spans the upgrade mixes the two methods.
Expect three changes once your apps run @yavio/sdk 0.5.4:
- The Sessions KPI drops for one period. Its trend compares with the previous period, whose one-call sessions (no
session_sourceyet) still count, while the current period'sper_requestrows do not. The drop is the correction, not lost traffic; the card's hint says how many calls had no session key. - Per-request hosts: VS Code and Codex traffic goes from one session per request to one per conversation — fewer sessions.
- stdio servers: VS Code and Codex sessions go from one per client process to one per conversation — more sessions, and
identify()no longer carries across the conversations of one VS Code process (a session keeps its own user).
ClickHouse 24.3 → 26.8 (one-way)
ClickHouse is pinned to 26.8.26.12. ClickHouse 24.x no longer receives security fixes.
This upgrade cannot be undone. Once 26.8 has started on your data, 24.3 refuses to start on the same volume. The only way back is a backup taken before the upgrade.
-
Take a cold backup of the ClickHouse volume. Stop ClickHouse only, archive its volume, then continue:
docker compose stop clickhouse VOLUME=$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/var/lib/clickhouse"}}{{.Name}}{{end}}{{end}}' "$(docker compose ps -a -q clickhouse)") docker run --rm -v "$VOLUME":/data -v "$PWD":/backup alpine tar czf /backup/clickhouse-before-26.8.tgz -C /data .ClickHouse's own log tables (
system.query_log,system.metric_logand others) can be most of that volume. To shrink the backup, truncate them before stopping ClickHouse, e.g.TRUNCATE TABLE system.metric_log. -
Pull and start:
docker compose pull clickhouse && docker compose up -d. Migrations run as usual. -
Clean up. The new version, and the system-log retention the compose file now mounts (see below), redefine ClickHouse's log tables. ClickHouse keeps the old ones under a numbered name. List and drop them:
SELECT name, formatReadableSize(total_bytes) FROM system.tables WHERE database = 'system' AND match(name, '_log_[0-9]+$'); -- then, per table: DROP TABLE system.<name>
ClickHouse's own logs are now kept for 30 days, and the server logs at warning level. The settings are in packages/db/clickhouse/config.d/system-logs.xml, which docker-compose.yml mounts. Previously these tables grew without limit.
CLICKHOUSE_ERASER_PASSWORD is required
The dashboard deletes account, workspace and project data as the yavio_eraser ClickHouse user, which can delete rows from the events table and do nothing else. It used to fall back to the unrestricted default user when CLICKHOUSE_ERASER_PASSWORD was unset. It no longer does: Compose refuses to start without the variable, and the dashboard exits at startup with a message naming it.
If your .env predates the variable:
echo "CLICKHOUSE_ERASER_PASSWORD=$(openssl rand -hex 24)" >> .env
docker compose run --rm migrate # applies the password to yavio_eraser
docker compose up -dRun the migration before starting the new dashboard, so the password is in place when the first deletion happens.
Only Yavio's roles can connect to Postgres
Migration 0008 revokes CONNECT on the Yavio database from PUBLIC and grants it to yavio_app and yavio_api. Before, any role in the Postgres server could connect just by existing. Yavio's own services are unaffected, and so are the owner (yavio_service) and superusers.
If a role of your own connects to the database, a read-only reporting user for example, grant it access after upgrading:
GRANT CONNECT ON DATABASE yavio TO my_reporting_role;Rollback
If an update causes issues, you can roll back to a specific image version by pinning the version in your docker-compose.yml or using a tagged image:
docker compose pull dashboard:v1.2.3
docker compose up -d dashboardBackup Before Upgrading
For production deployments, take a backup before upgrading. With the backup scripts installed (Backups & Operations), run them by hand:
sudo /usr/local/bin/yavio-pg-backup.sh
sudo /usr/local/bin/yavio-clickhouse-backup.sh
sudo tail -2 /var/backups/yavio/backup.log # two "ok" linesA SELECT … FORMAT Native export of the events table is not a backup. It loses the materialized views, the users and the row policies.