Platform

Limits

All orgs on a deployment share the same processes, containers and database. Limits stop one org from using up the server, the disk or the shared keys for the other orgs. Each module declares its limits, and the superadmin can change them for each org.

Kinds of limit

KindCapsExampleOver the limit
CountHow many of a thing the org keepsknowledge.sources, godfather.pods409, nothing is added
RateHow much the org uses in a minute, an hour or a dayknowledge.embeddings_per_day, mcp.calls_per_minute429, nothing is counted

A rate counter starts again at the start of each window, in UTC. The usage_counters table keeps the counters, and the limits.prune job deletes counters older than 8 days.

Limits and defaults

KeyModuleLimitDefault
knowledge.sourcesknowledgeSources, crawled, uploaded or written by a client1,000
knowledge.passagesknowledgePassages of the current versions of all sources250,000
knowledge.embeddings_per_dayknowledgeTexts embedded a day, for knowledge and agent memory500,000
knowledge.uploads_per_dayknowledgeFiles uploaded a day500
knowledge.jobs_per_dayknowledgeCrawls, re-indexes and re-embeds that an officer or a token starts200
godfather.podsgodfatherPods10
runpod.appsrunpodHosting apps25
uptime.monitorsuptimeUptime monitors50
event_webhook.webhooksevent_webhookEvent webhooks20
submodules.subscriptionssubmodulesSubmodules the org subscribes to. Their shared pages count against no org20
mcp.calls_per_minutemcpTool calls a minute, over MCP and /api/tools. Each call in a batch counts300

Each embedding counts, whichever service the org uses. A search over the embedding limit searches on text only and does not fail. A crawl or an upload over a limit records the error on the source or the file, and the other sources and files go on.

Who pays

Each limit says who pays for what it counts (paid_by), so an officer sees what uses the org's budget.

paid_byMeansExampleCounts against the org
orgThe org's own data and appsIts own knowledge sources, its pods and appsYes, as counts. The default for a count limit
meteredA shared service the org usesThe deployment's embedder, the shared MCP server, the job workerYes, as rates. The default for a rate limit
sharedContent the deployment makes once for every orgA submodule's pagesNo. It has no limit of an org

A limit can name the integrations whose deployment default it meters (integrations=("embeddings",)). When an org uses the deployment's key for such an integration, the Integrations tab says which limits its use counts against.

The dashboard shows who pays:

  • Settings > Limits puts the org's own limits and the metered ones in two groups.
  • A module card on Explore lists the limits that its use counts against.
  • The Submodules tab marks each part of a submodule: its pages are shared, its live query results and feeds are the org's own.
  • The Integrations tab shows "Platform's key" and the limits it counts against, or the org's own key.

The value of a limit

The value for an org is the first of these that is set:

  1. The org's override. The superadmin sets it on the Superadmin page or with PUT /api/superadmin/limits/<org_id>. The org_limits table keeps it.
  2. LIMIT_<KEY> in .env: the key in upper case, with _ for .. For example, LIMIT_KNOWLEDGE_SOURCES=200. The value unlimited removes the limit.
  3. The default in the table above.

An override can be a whole number, null (no limit) or "default" (remove the override).

Where to see them

  • Officers see the limits of the modules that are on, and what the org uses, on Settings. GET /api/organizations/<org_id>/limits returns the same list.
  • Agents call the org.limits tool (scope org:read).
  • The superadmin sees each org, its use and its overrides on the Superadmin page, with GET /api/superadmin/limits. A limit that the org uses 80% of or more is marked.

Other protections

ProtectionSettingDefault
One run at a time of knowledge.reindex and knowledge.reembed for each org, and of knowledge.crawl_source for each source. A second request gets 409once on the job in core/jobs.pyon
Jobs that run at the same time in a process with the inline (SQLite) backendJOB_THREADS4
The crawl of due sources takes one source of each org in turn. Orgs that are inactive or have knowledge off are left outKNOWLEDGE_CRAWL_BATCH20
The largest request body, in MB. A bigger body gets 413MAX_REQUEST_MB110
Memory and CPU of each container*_MEM_LIMIT, *_CPUS. See Operationssee Operations

Add a limit to a module

  1. Declare the limit at the top of the module's service.py with limits.declare(...) from core/limits.py. A count limit needs a usage function that counts what the org has. A rate limit needs a window. Set paid_by when the default (org for a count, metered for a rate) is not right, and integrations when the limit meters an integration's deployment default.
  2. Before the module adds a thing, call limits.check(db, org_id, KEY). For a rate, call limits.consume(db, org_id, KEY, amount) before the work.
  3. Add the limit to the table on this page and to the module's README.md.

consume() flushes and does not commit. If the request fails and rolls back, the use is not counted. A read route that consumes must commit.

Not limited yet

  • Container limits cap each service, not each org. One org can still use all of the API's memory.
  • Data is kept apart by organization_id in the code. The database does not enforce it.
  • Agent conversations and memories have no count limit, only AGENT_RETENTION_DAYS.
  • Points, store, calendar and LeetCode data have no limits. They are small.

On this page