Skip to main content
A platform asks one question no single tenant can answer: across all my tenants, which are turning? Each tenant is a namespace Brussle keeps apart on purpose, so nothing reads across them. A tenant summary is the one way up: a template publishes a tenant document per namespace under it, into the template’s own namespace, built from that tenant’s groups and banded. Your platform then defines ordinary judgments, queries and subscriptions over the tenant documents. Only bands cross the boundary. A tenant document holds band labels, never an aggregate’s value, and never a key value you did not list: key values come from your tenants’ attributes. A judgment over tenant documents reads no tenant’s text, only the labels each tenant published. It is the one relation that crosses namespaces, and only upward.

Set one up

Say every tenant under acme/prod/* has a template group abuse_by_day, keyed by a day bucket you write and keeping the last 7 days, and by_plan, keyed by plan. Choose the groups each tenant publishes, a band for each aggregate you want to judge by, and the key values you want published one by one:
POST /v1/namespaces/acme%2Fprod%2F*/tenant_summary
Every group must exist on the template, and every key of bands names one of their aggregates as <group>.<aggregate>, as a group’s rows key them. A value takes the label of how many cut points are at or below it, so each band has one more label than cut points. keys is optional: each group it names must be one of groups, with the key values you want broken out. Templates need the Team plan or above.

The tenant document

Once an hour a run reads each tenant’s group rows and writes its document into the template’s namespace, here acme/prod:
  • id is the tenant’s namespace name, and attributes.kind is tenant.
  • state.groups holds labels only. Each group’s all bands its aggregates over all its key values together: here, the abuse count over the 7 days abuse_by_day keeps. A group you listed in keys also has keys, the labels of each listed key value the tenant has; this tenant has no free row, so free is absent. An aggregate without a band does not appear, and neither does a key value you did not list.
  • state.source says where the labels came from, without any of the tenant’s data: the position in the tenant’s history they are exact at (as_of).
A run writes a tenant’s document only when its labels moved, so a quiet tenant costs nothing to keep current. A tenant none of whose groups has rows yet has no document.

Judge your tenants

A tenant document is an ordinary document, so a judgment reads it like any other:
POST /v1/namespaces/acme%2Fprod/judgments
It is judged when a tenant’s labels move, queried like any judgment, and a subscription on it tells you when a tenant turns. Its audit stops at the tenant document: the labels it read, and state.source, the position in the tenant’s history they are exact at.

How current it is

GET lists each tenant by name with its status:
GET /v1/namespaces/acme%2Fprod%2F*/tenant_summary
A group’s rows are at most about an hour behind its tenant’s writes, and the run reads it once an hour and pages through your tenants. So a tenant document lags its tenant by up to a run plus the paging, not one hour: read published_at and source_as_of rather than assuming.

Changing it

  • Groups, bands and keys change with PATCH, each replacing the setting whole. The next run rewrites every tenant document whose labels move, which re-judges each of them, so a PATCH without "confirm": true changes nothing and returns what that costs: one line per judgment on the template’s namespace that reads tenant documents. Send it again with "confirm": true and it applies from the next run, unattended.
  • Delete with DELETE. Runs stop; the tenant documents stay, as ordinary documents.

Tenants that come and go

  • A tenant created under the template gets its document at the first run after its groups first have rows.
  • A tenant deleted and created again under the same name has its document deleted and written anew, so the history of anything judging it splits at the new incarnation, as it does for the tenant itself.
  • A tenant document is deleted only once a strong read says the tenant’s namespace is deleted, never because a listing missed it.

Billing and failures

Tenant documents are written like any write to the template’s namespace: they bill your organization as writes and stored bytes, and judgments over them bill as any judgment does. An idle tenant writes nothing. If the template’s namespace refuses the writes, for example because it is over its budget with on_exceeded: reject, the tenant summary shows the warning tenant_summary_failed and the events feed carries one namespace.tenant_summary_failed for the run, with the reason. Nothing is lost: the next run that can write catches every tenant up and clears the warning.