# Limits

Every hard number — file sizes, file counts, storage, retention, domains and deploy rate — per plan.

Every number the platform enforces, in one place. Where a limit is per-plan it is
listed per-plan; where it is the same for everyone it says so.

## Per plan

| | Free | Starter | Pro | Business |
| --- | --- | --- | --- | --- |
| Sites | 3 | 10 | 25 | 100 |
| Custom domains | — | 1 | 5 | 25 |
| Largest single file | 10 MiB | 25 MiB | 50 MiB | 100 MiB |
| Files per site | 500 | 2,000 | 20,000 | 50,000 |
| Storage | 1 GiB | 5 GiB | 25 GiB | 100 GiB |
| Releases kept | 5 | 20 | 50 | 100 |

Plans and what they cost are on the [pricing page](/pricing). Changing plan
takes effect the moment the payment clears.

## What each one actually counts

**Files per site** is the number of files in one release — what the site serves.
It is not cumulative across releases.

**Storage** counts **distinct content** across your whole account, not the sum of
your releases. Every file is stored once by its hash, so a release that changes
one page adds one page's worth of bytes, and twenty releases of a 500-file site
cost barely more than one. This is why keeping history is close to free, and why
deleting old releases usually frees less than you would expect — the bytes are
shared with the releases you kept.

**Releases kept** is count-based retention on *untagged* releases, so how far you
can roll back does not depend on how often you ship. Older ones age out.

**Largest single file** is per plan, and Business's 100 MiB is where the ladder
ends: that is the storage layer's structural ceiling, so no plan can promise a
file larger than it can write. If you are pushing single files near your plan's
number, that is usually video, and a video host will serve it better than a
static host will.

**Custom domains** count www-stripped hostnames: `example.com` and
`www.example.com` together use one slot. Any other subdomain is its own.

## The same on every plan

| | |
| --- | --- |
| Tags per site | **5**. Tagged releases never age out, so this bounds how much history one site can pin. At the cap a tagged release fails rather than quietly dropping a tag — `one9x pages releases rm` frees a slot. |
| Deploys | **60 per hour** per account. Comfortably above a busy CI pipeline; it is there to bound a runaway loop. |
| Site name | A DNS label: 1–63 characters, lowercase letters, digits and hyphens. |

## When you hit one

The limit is checked before anything is uploaded, and the message names the
number and the file:

```console title="over the file-count limit"
$ one9x pages release ./dist --site mysite --deploy
this deploy has 812 files, and your plan allows 500 per site
```

```console title="a single file is too big"
$ one9x pages release ./dist --site mysite --deploy
"/video/intro.mp4" is 18.4 MiB, and your plan's limit is 10 MiB per file
```

```console title="out of storage"
$ one9x pages release ./dist --site mysite --deploy
this deploy needs 240 MiB and your account is using 0.97 GiB of its 1 GiB —
free up space by deleting old releases or sites, or upgrade the plan
```

Nothing is half-uploaded when this happens: the check runs at declare time,
before the first byte moves, so a rejected deploy leaves the site exactly as it
was.

If a build is close to the file-count limit, `--exclude` is usually the shortest
fix — source maps and a stray `node_modules` account for most of it. See
[Deploy from the CLI](/docs/cli).