# Limits

Checked against the code on 2026-10-31 (version 0.1.0).

Every number below is a constant in the source; MB here means the unit written in the code (decimal "100 MB" = 100 000 000 bytes; "MiB" = 1 048 576 bytes).

> **Note:** plan limits are in the code as data and are measured (see "Plans and accounts" below), and billing by Pix and boleto is in the code too, off until the administrator sets the Asaas key ([billing API](/docs/api/#billing)); the hosted plans open with the first public server ([pricing](/pricing/)). On your own server, disk and network are the real limit.

## Deploys (with a token)

| Limit | Value |
|---|---|
| Request body (zip, HTML, one uploaded file, JSON) | 100 MB (100 000 000 bytes) |
| Files per deploy | 50 000 |
| Path length | 1 024 characters; no `.`/`..` or empty segments, no `\`, no NUL |
| HTML analysed for the SEO/GEO report and forms | files up to 2 MB (2 000 000 bytes); larger files are served but not analysed |
| `title` / `source` query options | 200 / 32 characters |
| `x-sdh-actor` header | 64 characters |
| Deploys kept | all; 0.1.0 never deletes deploys automatically |

## .zip uploads

| Limit | With a token | Anonymous drop |
|---|---|---|
| Entries in the zip | 20 000 | 20 000 |
| Total size uncompressed | 500 MiB | 50 MiB |
| One file uncompressed | 100 MiB | 25 MiB |
| Compression ratio (files above 1 MiB) | at most 200:1 | at most 200:1 |

Also: only "stored" and "deflate" compression; no ZIP64; no multi-volume zips; no password-protected entries; the CRC32 of each file is checked. `__MACOSX/` and common junk files are skipped. When every file sits in one top-level folder, that folder becomes the site root.

## Publishing without an account (drop)

| Limit | Value |
|---|---|
| Availability | off unless the server runs with `SDH_ANON_DROP=1` |
| Request size | 25 MiB (the CLI checks before sending) |
| Rate | 5 per network per hour (one IPv4 address, or one IPv6 `/64`); every attempt counts, including refused ones (`429`, `Retry-After: 3600`) |
| Server-wide cap | `SDH_ANON_DROP_MAX_HOUR` drops per hour for the whole server, default 60 (`429`, `Retry-After: 600`) |
| At the same time | 2 drops processed at once; more answer `503` (`busy`, `Retry-After: 10`) |
| Total storage | `SDH_ANON_DROP_MAX_MB`, default 2048 MiB for all drops together (`503`, `drop_quota`, `Retry-After: 3600`) |
| Lifetime | 24 hours unless claimed; expired drops answer `410` and are removed within about 10 minutes |
| Restrictions until claimed | always `noindex`, forms off (`403`), redirects/proxy to other sites ignored, no functions, no CSP / `Service-Worker-Allowed` / `Access-Control-*` headers |
| Claim code | shown once; only its SHA-256 is stored |

Rate counters (drops and forms) live in the server's memory and start again from zero when it restarts.

## Forms

| Limit | Value |
|---|---|
| Submission body | 1 MB (1 000 000 bytes) |
| One field value | 10 000 characters (longer values are cut) |
| Rate | 10 submissions per minute per IP per site (`429`, `Retry-After: 60`) |
| Links | more than 3 `http(s)://` links → marked as spam |
| Detection | up to 200 forms per page, 200 fields per form |

## Proxy rules in _redirects

| Limit | Value |
|---|---|
| Target | public IP addresses only |
| Timeout | 10 seconds |
| Target address | checked again at connection time; redirects are not followed |
| Answer size | 10 MB (10 000 000 bytes), counted while reading |

## Functions (only with `SDH_FUNCTIONS=1`)

| Limit | Value |
|---|---|
| Time | 10 seconds (`SDH_FUNCTIONS_TIMEOUT_MS` can lower it, never raise it); then `504` |
| Memory | 128 MB per worker |
| Request body | 6 MiB (`413` above it) |
| Response body | 6 MiB |
| Running at once | 32 workers for the whole server; more answer `503` |
| Function name | `A-Z`, `a-z`, `0-9`, `_`, `-`, 1–64 characters |
| Code | one `.js`, `.mjs` or `.cjs` file per function, no `require` of other files or `node_modules` |

## Plans and accounts

The numbers of the three plans live in `packages/core/src/plans.ts`. Sites that existed before accounts, and sites created with the server token, belong to the `principal` account, which is on the Agency plan.

| Item | Free | Pro | Agency |
|---|---|---|---|
| Sites in the account (anonymous drops do not count) | 3 | 25 | 150 |
| Bandwidth per month (soft limit: a warning, never a block) | 30 GB | 300 GB | 2 048 GB |
| Form leads per month (a lead over the limit is always kept) | 100 | unlimited | unlimited |
| Deploys | unlimited | unlimited | unlimited |

- 1 GB here is 1 024³ bytes. Months are counted in UTC.
- **Sites** are the only hard limit: creating or claiming a site beyond the plan answers `402 plan_limit`, and nothing that is live is touched.
- **Bandwidth and leads** only produce a warning (`estado: aviso`). Over a limit for two months in a row, a plan change is requested with 14 days to do it (`estado: pedir_troca`). No site is switched off and no lead is lost.
- **Failed payment:** when an invoice is overdue the state is recorded and there are 30 days to pay with everything as it is. After that the sites still stay live and nothing is deleted; only creating a new site follows the Free limit (3 sites) until the invoice is paid.
- **Subscription attempts:** 5 new checkouts per account in 24 h (`429 checkout_limit`); repeating the same request with the same `Idempotency-Key` does not count.
- Bandwidth is summed in memory and written once a minute, without IP or path.
- Read it all with `GET /v1/account/usage`, `sdh uso` or MCP `get_usage`.

| Item | Rule |
|---|---|
| Active tokens per account | 20 (the 21st answers `409 token_limit`) |
| Revoked tokens | kept in the list for 90 days, then removed |
| Token label / account name | 100 characters |

## Names and keys

| Item | Rule |
|---|---|
| Site name | 1–63 characters, `a-z`, `0-9`, `-`; not starting or ending with `-`; no `--` |
| Reserved site names | `www`, `api`, `app`, `admin`, `edge`, `mcp`, `status`, `docs`, `mail`; names starting with `site-`, `dpl-`, `acc-` or `tok-` (they look like internal ids) |
| Variable name | `A-Z`, `0-9`, `_`, not starting with a digit, up to 128 characters |

## Lists

| List | Range (default) |
|---|---|
| `GET /v1/sites/{site}/deploys?limit=` | 1–100 (20) |
| `GET /v1/sites/{site}/submissions?limit=` | 1–500 (50) |
| `GET /v1/audit?limit=` | 1–500 (50) |
| MCP `deploy_files` | 1–500 files per call |
| MCP `list_deploys` / `list_leads` | 1–100 (10) / 1–200 (50) |
| `sdh comparar --max` / MCP `compare_sites` | pages per site, default 500; MCP accepts 1–2 000 |

## Not limited in code

Number of `_redirects` / `_headers` rules, number of custom domains per site and storage. These are bounded only by your server. Sites and bandwidth are bounded by the plan of the account, as described above.
