Limits That Are Not Plan Limits

Every number on this page is fixed in the product. It is the same on Free and on Enterprise, it does not appear on an invoice, and upgrading will not move it. When you hit one of these, the answer is in the last column of a table, not in a plan change.

How to tell which kind of limit you hit

You can tell the three kinds apart from the response alone, before you know anything about the feature.

  • A 400 — or a form that refuses before it submits — is a fixed ceiling. It is on this page.
  • A 402 upgrade_required is a plan quota or a feature gate. Those live on Usage and Limits and When a Feature Is Gated.
  • A 200 with nothing in it is neither. It is a gate that degrades silently instead of returning an error, and When a Feature Is Gated names the ones that behave that way.
flowchart LR
    A["400, or the form<br/>refused to submit"] --> D["Fixed ceiling<br/>— this page"]
    B["402 upgrade_required"] --> E["Plan quota or feature gate<br/>— Usage and Limits"]
    C["200, but empty or<br/>missing data"] --> F["Silent degradation<br/>— When a Feature Is Gated"]
    A -.- A1["Same on every tier.<br/>Upgrading changes nothing."]
    B -.- B1["Body names the feature,<br/>your tier and the tier needed."]
    C -.- C1["No error at all.<br/>The widget just never fills."]

Analytics

A single analytics query may span at most 365 days. The guard is shared by every analytics route — Know, page analytics, forms and short-code reporting — so none of them can drift from the others.

LimitValueWhat happens when you hit itWhat to do instead
Span of one analytics query365 days400 — Range cannot exceed 365 daysSplit the question into two queries and add the results
Direction of the rangeEnd must be after start400 — end must be after startReverse the dates

Uploads and files

LimitValueWhat happens when you hit itWhat to do instead
Image upload sizeStrictly under 10 MBThe upload modal refuses before the file is read, hashed or croppedCompress or resize — Uploading Images
Image file typepng, jpeg, gif, webp, svgThe modal refuses with the accepted listConvert the file, or upload it as a different kind of asset
Repository file size500 KB per fileleed site validate and leed site commit refuse the commit and name every oversized fileMove the asset into the CMS asset library instead of the repository
Repository file extensionsMedia, archives, office documents and fonts are refusedThe same refusal, listing the disallowed extensionsUpload it as an asset and reference it by URL
OpenAPI spec fileUnder 25 MBA hard error at generate time and again at upload — never a truncationSplit the spec, or trim examples out of it

Both upload refusals are shown to you verbatim:

Image is 12.4MB. Images must be under 10MB.
Valid file types are: png,jpeg,gif,webp,svg

Two details worth knowing before you argue with the first one. The size in the message rounds up to a tenth of a megabyte, so a file one byte over reads as 10.1MB rather than 10.0MB. And the check is client-side only — it protects the upload modal, not the platform, so a caller working through the API is not stopped by it and should apply the same ceiling itself.

The 500 KB repository rule is the one number here that a self-hosting operator can change: the build reads FILE_VALIDATION_MAX_SIZE from the environment and interprets it in kilobytes, not bytes. It is not a per-workspace setting and there is no CMS control for it. The rest of the repository validation — the read-only files, the protected paths, the extension list — sits with it at File Validation Rules, and the CLI’s side of the refusal is leed site validate, commit and push.

Text field caps

LimitValueWhat happens when you hit itWhat to do instead
Social card title70 charactersThe value is rejected on saveWrite a shorter title — the card truncates in most feeds anyway
Social card description240 charactersRejected on saveShorten it
Page-type slug150 charactersRejected on saveShorten a segment; nested API roots count the separators too
Custom theme, code-theme and font name32 characters, ^[a-z0-9]{1,32}$400 naming the fieldUse lowercase letters and digits only, with no dashes
Form description400 charactersRejected on saveMove the long copy onto the page around the form

Batch and page-size ceilings

These are throughput mechanics rather than entitlements. Nothing here bills you, blocks you or shows an error — the work is split into more than one unit and proceeds. They matter mostly if you are calling Leed from a script or an MCP client and wondering why a result set stopped where it did.

Batch sizes and per-call page sizes
LimitValueWhat happens when you hit itWhat to do instead
Contact CSV fan-out10 contacts per queue messageThe import lands progressively rather than all at onceWait — the list fills in as the messages drain. Importing Contacts describes what you see
Marketing send fan-out100 recipients per batch messageThe blast is chunked; recipients are reached over several invocationsNothing; this is invisible except in timing
Engage segment membership1,000 members resolved per requestThe scored list stops at 1,000Narrow the segment
schedule_pages (Operator MCP)1–100 page ids per callThe call is rejected with a parameter errorSplit the schedule into several calls; every page in one call shares one time slot
Operator MCP list toolsPage size 1–100The page size is rejected outside that bandPage through with offset
Operator MCP content searchQuery 2–200 characters, limit 1–50Rejected outside those bandsShorten the query or lower the limit
Docs MCP page fetch25 pages per callRejected above 25Fetch in batches of 25
Docs MCP search results25 results maximumThe result list stops at 25Narrow the query

Each MCP tool states its own parameter bounds; Operator MCP Tool Index points at the right tool’s table.

Rate limits

Three rate limiters are deployed, all of them fixed and none of them plan-scoped.

LimitValueWhat happens when you hit itWhat to do instead
Authentication endpoints10 requests / 60 s, keyed on your Authorization header or your IPThe request is refused until the window rollsWait a minute; nothing is lost
Contact detail reads60 requests / 60 s, keyed on the requesting userThe read is refused until the window rollsPage through contacts instead of fetching them one at a time
Public site agent surface60 requests / 60 s, per IP429 with a JSON bodyBack off and retry

The agent surface is the only one of the three that answers with a body you can parse:

{ "error": "rate_limited" }

The authentication limiter deliberately exempts the paths a CLI login walks — the device-code request, the device-code polling loop, the OAuth callback, sign-out and every already-authenticated session read — so signing in a terminal is never throttled mid-poll. Sign-in itself, and anything that handles a credential, stays limited.

These are deployment configuration rather than source constants: they are read per environment, and every environment currently agrees on the values above. Treat them as the current production numbers, not as an API contract.

Time limits

LimitValueWhat happens when you hit itWhat to do instead
CMS session7 daysYou are signed out and returned to the sign-in screenSign in again; the session refreshes while you use it. Sessions, Connected Accounts and API Tokens
Magic link5 minutesThe link reports that it has expiredRequest a new one
Emailed one-time code5 minutesThe code is refusedRequest a new one
Device code (CLI and client authorization)5 minutes, polled every 5 secondsThe pending authorization lapsesRun the command again — Authorizing Devices and Clients
Build15 minutesThe deployment is marked failed as a safety netRetry the deployment; a genuine 15-minute build is a content problem, not a slow build
Domain Connect re-checkEvery 10 seconds, 12 times (2 minutes)Polling stops and the button becomes manualClick Check now once DNS has propagated
Scheduling horizon365 days aheadA slot further out is not offeredSchedule closer in and revisit

Display ceilings that are not limits at all

These are presentation and storage choices. Nothing is refused; you are simply not shown everything.

LimitValueWhat happens when you hit itWhat to do instead
Deployment historyLast 10 rows per columnOlder deployments drop off the Deploy tabNothing is deleted; the history is trimmed for the screen only
Build error summary2,000 charactersThe block you are shown is an extractTreat a truncated block as a pointer, not the whole story — When a Deployment Fails decodes it
Visitor cookie lifetime1 yearNothing; the cookie is refreshed as the visitor returnsNothing

The three that do move

These are the only numbers in Leed that change when your plan does. They are listed here so you can rule them out; the mechanics belong to Usage and Limits.

QuotaFreeStarterGrowthEnterpriseDocumented in
Identified contacts2501,00010,000UnlimitedUsage and Limits
Marketing emails per month05,00050,000UnlimitedUsage and Limits
Analytics retention30 days365 days730 daysUnlimitedDate Ranges and Retention

The contacts number is a visibility cap applied when contacts are read, not a gate on capture. Forms keep accepting submissions past it and nothing is discarded; you see the oldest contacts up to your allowance until you upgrade. A denial on any of these three arrives as a 402 upgrade_required, and When a Feature Is Gated covers what happens next.

Limits that do not exist

Readers arrive looking for these, so it is worth saying plainly that they are not here. Leed imposes no traffic limit, no unique-visitor limit, no bandwidth limit, no storage limit, no seat limit and no page-count limit, on any plan. Editors and pages are unlimited on Free. If you are hunting for the number at which your site gets throttled or your team gets billed for another seat, there is no such number to find — the capabilities that are absent rather than capped are named at What Leed Does Not Do.

ESC