Budgets at several levels
Say your product sells to companies (tenants), each company has teams, and each team has users. Every month, each tenant may spend 1,000 credits, each team 100, and each user 10. A user’s request has to fit all three: their own 10, their team’s 100 and their tenant’s 1,000.
In Limitry that’s three limits, one per level, and one check that names all three subjects.
1. One limit per level
Section titled “1. One limit per level”Each level is its own limit, with its own counts. The kind is your own label for each level:
| Limit | subject.kind |
amount |
window |
|---|---|---|---|
| 1,000 credits per tenant | tenant |
1000 | month |
| 100 credits per team | team |
100 | month |
| 10 credits per user | user |
10 | month |
In a limitry.json:
{ "limits": [ { "name": "Tenant credits", "subject": { "kind": "tenant" }, "amount": 1000, "unit": "credits", "window": "month" }, { "name": "Team credits", "subject": { "kind": "team" }, "amount": 100, "unit": "credits", "window": "month" }, { "name": "User credits", "subject": { "kind": "user" }, "amount": 10, "unit": "credits", "window": "month" } ]}Or create them from your code. Without a name, each is named after
its sentence, such as “1,000 credits per tenant per month”:
import { createClient } from "@limitry/sdk";
const limitry = createClient(); // reads LIMITRY_API_KEY
for (const [kind, amount] of [ ["tenant", 1000], ["team", 100], ["user", 10],] as const) { await limitry.limits.create({ subject: { kind }, amount, unit: "credits", window: "month", });}from limitry import Limitry
limitry = Limitry() # reads LIMITRY_API_KEY
for kind, amount in [("tenant", 1000), ("team", 100), ("user", 10)]: limitry.limits.create( subject={"kind": kind}, amount=amount, unit="credits", window="month", )In the app, create the first one, then click Add another limit: it opens with the same unit and period, so only the kind and the amount change.
2. One check that names all three
Section titled “2. One check that names all three”Limitry doesn’t know which team a user is in, or which tenant a team
belongs to. Your product knows, so each check says it: the user is the
subject, and the team and the tenant go in shared.
import { createClient, LimitReached } from "@limitry/sdk";
const limitry = createClient();
try { const report = await limitry.guard( { subject: { kind: "user", id: user.id }, shared: [ { kind: "team", id: user.teamId }, { kind: "tenant", id: user.tenantId }, ], action: "report", cost: 2, }, () => buildReport(params), );} catch (error) { if (error instanceof LimitReached) { // error.limitId says which level was used up. console.log(error.message); }}from limitry import LimitReached, Limitry
limitry = Limitry()
try: with limitry.guard( subject={"kind": "user", "id": user.id}, shared=[ {"kind": "team", "id": user.team_id}, {"kind": "tenant", "id": user.tenant_id}, ], action="report", cost=2, ): report = build_report(params)except LimitReached as error: # error.limit_id says which level was used up. print(error)curl -X POST https://api.limitry.com/v1/checks \ -H "Authorization: Bearer $LIMITRY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject":{"kind":"user","id":"usr_123"}, "shared":[{"kind":"team","id":"team_42"},{"kind":"tenant","id":"acme"}], "action":"report","cost":2}'The check is allowed only if the cost fits every limit on the user, on
the team and on the tenant. Then Limitry charges all three, or none:
a refused check uses nothing anywhere. The answer’s limits lists each
level with what is left on it, and when one is used up,
reason.limitId says which.
When the cost is known only afterwards, use reserve with the same
shared subjects. See Reservations.
3. Things to know
Section titled “3. Things to know”- Each level counts on its own. A user in two teams is counted on whichever team the check names. Name the team the work is for.
- Send the same kinds every time. A check that names
teamsinstead ofteamreaches no team limit. The Limits page flags a limit that no check has reached in 7 days, so a misspelt kind shows up there. - Up to 4 shared subjects. A user, their team, their tenant and a project fit in one check.
- One customer can get more. A limit for one subject, such as
{"kind": "tenant", "id": "acme"}with 5,000, replaces the tenant limit for that tenant only. See Limits.
To show each user where they stand on all three levels, call
usage.standing with the same shared subjects. See
Show users where they stand.
Related: Pools, balances and budgets, Checks.