# Limits

Every limit and rule for anonymous (unclaimed) folds, the error each one produces, and how to fix it.

Claimed folds (see [Claim](/fold/cli/#claim)) keep these limits for now, with one difference: they never expire. Outbound `fetch` and server secrets are coming soon for claimed folds too.

## Deploy

| Limit | Value | Error | Fix |
|---|---|---|---|
| Artifact size | 1 MB (1,048,576 bytes) | `Artifact is <n> bytes, past the 1048576 byte deploy limit.` | Remove unused code, large strings, and inline assets. |
| Deploy request size | 4 MB (artifact plus client bundle) | HTTP 413: `The deploy is larger than 4 MB.` | Shrink the client bundle. Do not inline images or data. |
| Favicon | 64 KiB | `Artifact favicon exceeds 65536 bytes.` | Use a smaller `.svg` or `.ico`. |
| New deploys per address | About one per 20 seconds, bursts of 10 | HTTP 429: `Too many new deploys from this address.` | Wait a few minutes, or redeploy the fold you already have. |
| Lifetime (unclaimed) | 7 days after the last deploy | HTTP 410: `This fold expired. Deploy it again to bring it back.` | Redeploy before it expires (each deploy resets the 7 days), or run `npx @aozumi/fold claim`: claimed folds never expire. |

Redeploying from the same directory keeps the URL and the data. If the fold already expired, `deploy` creates a new fold instead: a new deploy ID, usually a new URL, and an empty database.

Other deploy errors:

| Error | Cause | Fix |
|---|---|---|
| HTTP 401: `This deploy token doesn't match.` | `.fold/deploy.json` does not match the deploy. | Deploy from the directory that created the fold. |
| HTTP 409: `Could not find a free name for this fold.` | No free subdomain for this name. | Change `name` in `fold()` and deploy again. |
| `The database could not switch to this schema: ...` | Existing rows do not fit the new schema. | See [Schema changes](/fold/database-migration/). |
| HTTP 401: `This fold is claimed, so deploying it needs a developer token` | The fold was claimed and this computer is not signed in. | Run `npx @aozumi/fold auth login`, then deploy again. |
| HTTP 403: `This fold belongs to another workspace.` | You are signed in to a different workspace than the one that claimed the fold. | Run `npx @aozumi/fold auth login` and pick the fold's workspace. |
| HTTP 403: `Server secrets for claimed folds are coming soon.` | `.env.fold.server` has values. | Empty `.env.fold.server` and deploy again. |
| `AOZUMI doesn't support this command yet.` (HTTP 501) | You ran a command that is not available yet. | See [CLI](/fold/cli/#status-at-a-glance). |

## Source rules

Anonymous builds scan `server/` and `shared/` code (comments and strings are ignored) and reject:

| Not allowed | Error starts with | Fix |
|---|---|---|
| `fetch` | `Outbound fetch is disabled for anonymous deploys.` | Remove server-side fetch. Fetch from the browser, or have the other system `POST` to an endpoint. |
| `while (...)` loops | `while loops are not available in anonymous server code.` | Use `for...of` over a collection, or a `for` loop with a fixed bound. |
| `for (;...)` loops with no start | `Unbounded for loops are not available` | Give the loop a start and an end. |
| `setTimeout`, `setInterval` | `Timers are not available in anonymous server code.` | Do the work inline. |
| `eval(...)` | `eval is not available` | Write the logic out. |
| `Function(...)` | `Function constructors are not available` | Use `function` or an arrow. |
| `import(...)` | `Dynamic import is not available` | Use a static import. |
| `globalThis` | `globalThis is not available` | Keep state in `ctx.db`. |
| `process` | `process is not available in fold code` | Use `ctx.env` (claimed deploys only). |
| `node:` imports | `Node built-ins are not available` | Use `@aozumi/fold/server`. |
| `.where(`, `.orderBy(`, `.all(` | `where() is a legacy full-scan database API.` and similar | Use indexes. See [Database](/fold/database/). |

`Promise.all(...)` is allowed. Check these rules locally with `npx @aozumi/fold build --target anonymous`. The dev server does not enforce them.

Also, anywhere in the app:

- No npm packages other than Fold and Preact, and no Node built-ins.
- No CSS files, CSS modules, or PostCSS. Use Tailwind classes.
- The only static asset is the favicon.

If `fetch` is the only problem, or `.env.fold.server` has values, `deploy` does not fail. It publishes a placeholder page that says the app needs a claimed deploy. That page is not your app. Remove the server-side fetch and empty `.env.fold.server`, then deploy again.

## Server env

`.env.fold.server` values are not sent for anonymous deploys, a claimed fold refuses them for now, and `ctx.env` is empty when hosted. Use it only in local dev until hosted server secrets ship.

## Daily usage

Counters reset at 00:00 UTC.

| Limit | Value | What counts |
|---|---|---|
| Requests | 10,000 per day | Every HTTP request to the app (page loads, `client.js`, endpoints) and every message a page sends over its WebSocket (query subscriptions, mutations, actions). Sign-in and session checks do not count. |
| Mutations | 1,000 per day | Each mutation call, each action call, and each call to a writable endpoint. |

Error, as an HTTP 429 or a WebSocket error with a `code`:

```txt
This fold reached its daily request limit (10000). It resets at 00:00 UTC.     code: limit.requests_per_day
This fold reached its daily mutation limit (1000). It resets at 00:00 UTC.     code: limit.mutations_per_day
```

Fix: batch writes into fewer mutations, avoid calling mutations in loops from the client, and do not subscribe to queries you do not render.

## Stored data

| Limit | Value | Error |
|---|---|---|
| Total stored data | 1 MB | `State byte limit exceeded (1048576).` |
| Total rows | 16,384 | `State row limit exceeded (16384).` |
| One field value | 64 KiB | `Value for <table>.<field> exceeds 65536 bytes.` |

The mutation that would go over the limit fails and none of its writes are kept. Fix: delete old rows, store less per row, or keep summaries instead of raw events.

## Per call

| Limit | Value | Error |
|---|---|---|
| Query, mutation, endpoint run time | 10 seconds | HTTP 504 or call error: `Fold <kind> <name> timed out after 10000 ms.` |
| Action run time | 5 seconds | `Fold action <name> timed out after 5000 ms.` |
| Action arguments | 16 KiB | `Action arguments exceed 16384 bytes.` |
| Action result | 48 KiB | `Action result exceeds 49152 bytes.` |
| WebSocket message (query or mutation arguments) | 64 KiB | `Messages are limited to 65536 bytes.` |
| Endpoint request body | 2 MiB | HTTP 413: `Request body exceeds 2097152 bytes.` |
| Writes in flight per page | 4 | `Too many writes in flight on this connection (max 4). Await earlier writes.` The typed client queues for you. |
| Messages in flight per page | 32 | `Too many requests in flight on this connection (max 32).` |

Database budgets per call (rows read 5,000, rows returned 1,000, bytes read 4 MiB, 1,000 `get` calls, 100 index queries, 1,000 writes) are listed in [Database](/fold/database/#read-and-write-budgets). They throw `Database <name> limit exceeded (<limit>).`

## Not available yet when hosted

These answer `501` with a JSON `error` saying they are coming soon:

| Feature | Message |
|---|---|
| File storage (`client.storage`, `/storage`) | `File storage for hosted folds is coming soon.` |
| Logs (`npx @aozumi/fold logs <url>`) | `Logs for hosted folds are coming soon.` |
| Database access (`db list`, `db dump`, `db export`) | `Database access for hosted folds is coming soon.` |
| Inspect (`npx @aozumi/fold inspect <url>`) | `Inspecting hosted folds is coming soon.` |
| Access control (`users` approve and deny) | `Access control for hosted folds is coming soon.` |
| Tokens, deploy list, archive, restore, terminate, domains | `AOZUMI doesn't support this command yet.` |

`ctx.log` calls still run when hosted. There is no way to read them yet.
