---
title: "Limits"
description: "Per-workspace quotas by plan, and what happens when you reach one."
url: "https://saved.sh/docs/billing/limits"
---

Limits bound how much of the product a workspace uses. They are separate from
[pricing](/docs/billing/pricing), which bounds what it costs.

## The table [#the-table]

| Resource                   | Trial  | Paid      |
| -------------------------- | ------ | --------- |
| Workers per workspace      | 1      | 10        |
| Backups per workspace      | 5      | 100       |
| API keys per workspace     | 2      | 20        |
| Members per workspace      | 1      | 25        |
| Destinations per workspace | 1      | 25        |
| Connections per workspace  | 1      | 25        |
| Total stored               | 20 GiB | unlimited |
| One artifact               | 5 GiB  | unlimited |
| Retention window           | 7 days | unlimited |
| Workspaces per user        | 5      | 5         |

Read the live values rather than trusting this page:

```bash
curl -fsS "https://api.saved.sh/v1/workspaces/$WID/quotas" -H "Authorization: Bearer $TOKEN"
```

<Callout type="warn">
  In that response, a limit of **`0` means unlimited**, not zero.
</Callout>

## Limits are not prices [#limits-are-not-prices]

Nothing in this table is a revenue line. Each cap exists for a reason that is not billing:

| Cap                       | Why                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------- |
| Members                   | **Blast radius.** Permissions are workspace-wide, so every member sees every backup |
| Workers, API keys         | Credential sprawl is a security problem before it is a cost one                     |
| Destinations, connections | Each is a long-lived credential we hold on your behalf                              |
| Storage, on trial         | An unpaid workspace should not be able to store unbounded data                      |

A workspace of twenty pays the same as a workspace of one for the same usage.

## Two kinds of limit, two kinds of failure [#two-kinds-of-limit-two-kinds-of-failure]

**Counting limits** are checked before anything is created, so a refused call creates nothing:

```json
{ "error": { "code": "quota_exceeded", "message": "this workspace already has 5 backups" } }
```

**Size limits** cannot be checked in advance, because nothing about a request knows how large
a dump will be. They bind **during a run** and fail the run, not the API call.

<Callout type="warn">
  A trial workspace backing up a database larger than 5 GiB compressed will configure the
  backup successfully and then watch it fail at 02:00. Watch usage against the limit rather
  than waiting to find out.
</Callout>

## The retention cap is the one to plan around [#the-retention-cap-is-the-one-to-plan-around]

Trial caps the retention window at **7 days**, and retention is
[write-once](/docs/concepts/retention#retention-is-write-once).

<Callout type="error">
  **A backup created on trial keeps its 7-day policy even after you upgrade.** Upgrading lifts
  the cap for *new* backups; it cannot loosen an existing one, because retention cannot be
  edited at all. If you intend a 90-day retention, set it on a paid plan, or plan to recreate
  the backup.
</Callout>

This is the single most common thing to get wrong while evaluating. If you are trialling with
backups you intend to keep, either upgrade before creating them, or accept that you will
recreate them later.

## What is not limited [#what-is-not-limited]

| Not limited         |                                                   |
| ------------------- | ------------------------------------------------- |
| Runs per day        | Trigger as often as your source allows            |
| Concurrent runs     | Bounded by your worker and your source, not by us |
| Schedule frequency  | No minimum interval is enforced                   |
| Downloads and reads | Never gated, in any state                         |
| API calls           | No rate limit today                               |

<Callout>
  The absence of a run-rate limit is not an invitation. A run costs computation and produces an
  artifact that costs archive, so an over-frequent schedule is bounded by your bill rather than
  by a quota.
</Callout>

## Reaching a limit [#reaching-a-limit]

```bash
curl -fsS "https://api.saved.sh/v1/workspaces/$WID/quotas" -H "Authorization: Bearer $TOKEN" \
  | jq -r '.quotas[] | select(.limit != 0 and .used != null and .used >= .limit)
           | "at limit: \(.resource) \(.used)/\(.limit)"'
```

Worth running before applying a manifest that creates several backups, which otherwise fails
partway through with some created and some not.

To raise one: upgrade from trial, which lifts every counting limit and removes the storage and
retention caps. Beyond the paid defaults, ask.

## Billing state also gates writes [#billing-state-also-gates-writes]

Separately from quotas, an unpaid workspace stops doing new work.

| State                       | New runs | Config changes | Reads and downloads |
| --------------------------- | -------- | -------------- | ------------------- |
| `trial`, `active`, `warned` | Yes      | Yes            | Yes                 |
| `stopped`                   | No       | Yes            | Yes                 |
| `blocked`                   | No       | No             | Yes                 |

Reads and downloads are never gated in any state.

## Next [#next]

<Cards>
  <Card href="/docs/api/quotas" title="Quotas API" description="Reading limits and usage together." />

  <Card href="/docs/billing/credit" title="Credit" description="Starting without a card." />

  <Card href="/docs/concepts/quotas" title="Quotas" description="The concept." />
</Cards>
