# Limits

> The numbers that bound projects, buckets, uploads and requests.

| Limit | Value |
| --- | --- |
| Storage per bucket | 10 GB (10,737,418,240 bytes), counting stored zips and assets plus unfinished uploads |
| Chunk size | 16 MiB (16,777,216 bytes); the last chunk is shorter |
| Chunks per file | 1,000 |
| Whole-file download | Up to 1 GB; larger objects download chunk by chunk |
| Projects per account | 100 |
| Buckets per project | 100 |
| Preview: file size | 2 MB per file (bigger files stay in the zip) |
| Preview: per zip | about 96 MB of files and 20,000 files |
| Names | 80 characters (projects, buckets, backups); file names 255 |
| Descriptions | 500 characters |
| JSON request body | 16 KB |
| Requests per minute | Per key: 10, 30 (default), 60 or 120. Chunk uploads and downloads don't count toward it |
| Backups | Free: 1 per account |
| Tokens | Free: 1,000,000 per month (UTC calendar month) |

## Best practices

<AccordionGroup>
<Accordion title="Keep keys on the server" icon="shield">
Never ship a `clsk_` key in a browser, mobile app or public repository. Give each integration its own key with only the permissions it needs; a CI job that uploads needs `buckets:write`, a dashboard only `buckets:read`.
</Accordion>
<Accordion title="Upload in parallel, resume on failure" icon="upload">
Send 3 or 4 chunks at a time and retry a failed chunk. If the process dies, read `received_chunks` and send only what's missing.
</Accordion>
<Accordion title="Read with a ref" icon="zap">
Tree and file reads with `?ref=` are cached at the edge. Read `bucket.code.ref` once and reuse it.
</Accordion>
<Accordion title="Back up before big changes" icon="history">
Take a backup before uploading a zip that replaces the whole tree. Restoring is free.
</Accordion>
</AccordionGroup>
