very fast at protocol indexer with flexible filtering, xrpc queries, cursor-backed event stream, and more, built on fjall
rust
fjall
at-protocol
atproto
indexer
1---
2title: PDS management
3---
4
5hydrant rate-limits firehose events per PDS. each PDS is assigned to a named rate tier that controls how aggressively hydrant limits events from it. two built-in tiers are always present: `default` (conservative limits for unknown operators) and `trusted` (higher limits for well-behaved operators). additional tiers can be defined via `RATE_TIERS`.
6
7the per-second limit scales with the number of active accounts on the PDS: `max(per_second_base, accounts × per_second_account_mul)`.
8
9you can also define an optional `account_limit` for a rate tier. if a PDS exceeds this number of active accounts, hydrant will reject any new account creation events from it.
10
11the built-in tiers are:
12
13| tier | per_second_base | per_second_account_mul | per_hour | per_day | account_limit |
14| :--- | :--- | :--- | :--- | :--- | :--- |
15| `default` | 50 | +0.5 | 3,600,000 | 86,400,000 | 100 |
16| `trusted` | 5000 | +10.0 | 18,000,000 | 432,000,000 | 10,000,000 |
17
18tiers are resolved in this order: explicit API assignment (set via `PUT /pds/tiers`, stored in the database, survives restarts), then glob rules (from `TIER_RULES`, evaluated in order; first match wins), then the `default` tier (applied if nothing else matches).
19
20deleting an API assignment reverts the host to glob-rule resolution, not necessarily back to `default`. if a rule like `*.bsky.network:trusted` matches the host, it will become trusted again without any further action.
21
22## GET /pds/tiers
23
24list all current tier assignments alongside the available tier definitions. returns `{ "assignments": [{ "host": string, "tier": string }], "rate_tiers": { <name>: { "per_second_base": int, "per_second_account_mul": float, "per_hour": int, "per_day": int } } }`.
25
26`assignments` only contains PDSes with an explicit API assignment. hosts without one resolve via glob rules or fall back to `default`.
27
28## PUT /pds/tiers
29
30assign a PDS to a named rate tier.
31
32| field | description |
33| :--- | :--- |
34| `host` | PDS hostname (e.g. `pds.example.com`) |
35| `tier` | name of the rate tier to assign; returns `400` if unknown |
36
37assignments are persisted to the database and survive restarts. re-assigning the same host updates the tier in place without creating a duplicate.
38
39## DELETE /pds/tiers
40
41remove an explicit tier assignment for a PDS. query parameter:
42
43| param | description |
44| :--- | :--- |
45| `host` | PDS hostname (e.g. `?host=pds.example.com`) |
46
47reverts the host to glob-rule resolution (not necessarily `default`; a matching `TIER_RULES` pattern still applies).
48
49returns `200` even if no assignment existed.
50
51## GET /pds/rate-tiers
52
53list the available rate tier definitions. returns a map of tier name to `{ "per_second_base", "per_second_account_mul", "per_hour", "per_day", "account_limit" }`.