Skip to main content
Every team asks for the same dashboard numbers: “frustrated conversations by plan, this month”, “refund requests per merchant category”, “average first-reply time per region”. The usual answer is a warehouse job over an export. In Brussle it is a group: a group-by you declare once on a namespace. It keeps its aggregates per value of a key attribute, over your documents and over your judgments’ answers, and you read the rows whenever you want them. A group reports. It is not a query planner and not an input to a judgment: it keeps exactly the aggregates you declared, and nothing reads it but you. To give a judgment other documents’ facts or answers, use a relation.

Frustrated conversations by plan, this month

Say each conversation carries its account’s plan and the month it started, which you write anyway, and a frustrated judgment answers for each one. Write the key you want to report by as one attribute, here attributes.plan_month, such as "pro/2026-09":
POST /v1/namespaces/acme%2Fsupport/groups
The create returns 202 with the group building and its group_build job, which counts what the namespace already holds, including documents written just before. It judges nothing. Once it is done the group reads ready, and every later change is counted, at most about an hour after it is written. Sending the same create again returns the group; a create whose name another group already has, with other settings or inherited from a template, is conflict. Read the rows with a get:
GET /v1/namespaces/acme%2Fsupport/groups/frustration_by_plan
Rows come largest count first. A value is null when no document in the row has a number at that path. The dashboard’s Groups tab on the namespace charts the largest key values and lists every row beside the chart.

What a group keeps

count_where reads a judgment that answers on its own: active, on_change, and neither reading other documents nor combining parts. A raw probability is never summed or averaged, only counted by a bound or a named threshold, so the numbers you read are the ones you would query on. A group keeps at most 8 paths across its aggregates and count_where.

How current the rows are

The rows are exact as of one position in the namespace’s history, and as_of is that position. They catch up at least once an hour, so they are at most about an hour behind your writes, and on busy namespaces far less. A key value that no counted document has yet reads nothing until the rows next catch up. Answers count once the rows catch up with them too, under their document’s attributes at that point: a conversation moved to another plan counts under its new key from the update that moves it.

Changing a group

  • Add aggregates with PATCH and {"aggregate": {...}}: the group reads building while a new group_build job counts them, then ready. An aggregate never changes meaning and is never removed; a group has at most one count_where. To report something else, create another group.
  • Change keep_keys with PATCH, at once.
  • Delete with DELETE. It judges nothing and changes no answers.

Limits

  • 8 groups per namespace, counting those it inherits from a template.
  • 1,000 live key values per group. A key value is live while it has a matching document created within keep_keys (90 days by default), so a month or day bucket ages out on its own. At create, a key attribute with more live values than that is refused with invalid_request: key the group on something coarser, such as a merchant category instead of a merchant. A group that grows past it later carries the warning group_over_cap, and its rows hold the 1,000 key values with the largest count until older ones age out.
See limits for every number.

On a template

A group created on a template prefix, such as acme/prod/*, exists in every namespace under it, each counting only its own documents. Read each tenant’s rows on its own path; the prefix path returns the definition with rows: null. A tenant cannot change or delete a group it inherits (conflict). A template’s tenant summary publishes their bands, never their values, as a document per tenant.

Accuracy

A group counts what your documents and answers say. It makes no claim about how accurate those answers are: count_where is as good as the judgment it counts, and measuring and improving it is how you know.

Cost

A group never calls an engine, so it adds no judgments to your bill. Its counts are stored beside your data, a small amount of storage, and count toward the namespace’s stored bytes.