tracera
Platform

Multi-tenant model

Tracera was multi-tenant on day one — not bolted on. The tenant boundary is the hardest line in the system.

The hierarchy, again

Platform
└── Tenant            ← hard isolation lives here
    └── Brand
        └── Property
            └── Domain(s) / bundle-IDs

Tenant isolation

Three layers enforce that nothing in tenant A is ever visible to tenant B:

  1. Query layer. Every analytics query is constructed by Tracera, never accepted as raw SQL from clients. The query builder requires a tenant_id on every call and the type system makes it impossible to omit.
  2. Database layer. The ClickHouse events table is partitioned by (tenant_id, month) and the ORDER BY is (tenant_id, property_id, event_time). Cross-tenant joins are not just blocked — they have no shared index path and would be glacially slow.
  3. Token layer. Every API token is bound to exactly one scope <= tenant. The authorisation middleware refuses any request whose URL parameters refer to a scope outside the token's authority.

Brands

A brand is a UI concept: shared theming, shared aggregate "all-brand" rollups, and a shared roster of brand_manager users. Brands inside a tenant share infrastructure but get separate dashboards.

Properties

A property is what you actually instrument. One web app is one property; one iOS app is another. Each property has its own public ingest key, its own allowed domains (or bundle IDs), and its own retention policy.

Cross-tenant data?

There isn't any — not for the platform owner, not even by accident. If you operate Tracera for many customers (e.g. an agency model), each customer is a tenant and you would issue separate logins. Aggregate "how is our overall business doing" reports are done by exporting per-tenant numbers and rolling them up in your own BI tool.

Deletion