Managed storage
Managed storage is the default. CAVS runs the bucket and everything around it; you push and pull. In production it runs on Cloudflare R2.
What CAVS administers
Section titled “What CAVS administers”| Concern | Handled by CAVS |
|---|---|
| Bucket and credentials | provisioned and rotated by CAVS |
| Encryption at rest | R2 server-side encryption |
| Durability and backups | provider durability plus CAVS-side integrity checks |
| Lifecycle and retention | CAVS policy |
| Garbage collection | unreferenced chunks reclaimed by the worker |
| Repack and compaction | worker-driven, see Lifecycle |
| Egress | included up to your plan’s limit, then metered |
| Integrity verification | per-chunk BLAKE3, per-object SHA-256, Merkle roots |
You get none of the bucket-administration work and none of the bucket configuration risk. The trade is that the bytes live in CAVS’s account — if that matters for your compliance posture, use Bring Your Own S3 instead.
How keys are laid out
Section titled “How keys are laid out”Every repository has a storage namespace, and two sub-trees live under it:
<namespace>/objects/<oid[0:2]>/<oid[2:4]>/<oid> whole objects<namespace>/cas/<tree-relative path> the CAVS chunk treeobjects/…holds whole objects, written by upload sessions and by standard Git LFS transfers. Two-level sharding on the oid keeps any one prefix from getting hot.cas/…holds the content-addressed chunk tree produced by the CAVS transfer agent: asset manifests, chunk maps and immutable packfiles.
Both are content-addressed, so a write of identical bytes lands on the same key and costs nothing extra.
How bytes get in and out
Section titled “How bytes get in and out”Managed storage is never proxied through the API. Every transfer runs against a presigned URL valid for 15 minutes:
| Operation | Path |
|---|---|
| Upload | POST …/uploads/{session}/objects → presigned PUT |
| Download | POST …/downloads/authorize → presigned GET |
| Git LFS | POST …/lfs/objects/batch → presigned PUT/GET per object |
| CAVS chunk tree | GET/PUT/HEAD …/lfs/* — proxied, with Range support |
The chunk-tree path is the exception: those requests do pass through the API, because the agent needs authorized range reads over a content-addressed tree. They are small, cacheable reads, not whole-object transfers.
Quotas and metering
Section titled “Quotas and metering”Managed storage counts against your plan on two axes:
| Metered | Basis |
|---|---|
| Storage | physical bytes — post-dedup, post-compression |
| Egress | bytes served on downloads, per calendar month |
Because storage is billed on physical bytes, deduplication is a direct discount: ten similar 1 GB checkpoints that share most of their chunks cost far less than 10 GB.
| Plan | Included storage | Included egress/month | Max object size |
|---|---|---|---|
| Free | 10 GiB | 20 GiB | 5 GiB |
| Developer | 100 GiB | 250 GiB | 50 GiB |
| Team | 1 TiB | 2 TiB | 200 GiB |
| Business | 10 TiB | 10 TiB | 1 TiB |
Beyond the included amount, overage is metered per GB — see Plans & quotas.
When a quota is hit
Section titled “When a quota is hit”Storage is checked before a batch of uploads is authorized, using logical sizes as an upper bound (dedup lands the real figure lower). So a batch that would clearly overflow is refused up front rather than half-written:
{ "error": { "code": "quota_exceeded", "message": "storage quota exceeded for plan developer", "request_id": "8c1f…", "details": { "reason": "storage", "limit": 107374182400, "used": 106300000000 } }}Warnings fire before the wall: storage.quota.warning at the threshold, then
storage.quota.exceeded. Both raise a notification, send an email and fan out to
your webhooks.
Watching usage
Section titled “Watching usage”export API=https://cavsnode.com/api/v1export H="Authorization: Bearer $CAVS_TOKEN"
curl -sS "$API/organizations/acme-ai/usage" -H "$H"curl -sS "$API/organizations/acme-ai/usage/series?days=90" -H "$H"curl -sS "$API/repositories/$REPO/usage" -H "$H"cav storageFigures come from an asynchronous reconciliation that sums the real stored bytes under each namespace, so they lag a push by seconds. See Storage insights.
Managed vs BYOS
Section titled “Managed vs BYOS”| Managed | BYOS | |
|---|---|---|
| Where the bytes live | CAVS’s R2 account | your bucket, your account |
| Who pays for storage and egress | CAVS, within your plan | you, to your provider |
| Counts against CAVS quotas | yes | no |
| Bucket administration | CAVS | you |
| Available on | every plan | Developer (add-on), Team, Business |
| Data residency control | no | yes |
| Compliance boundary | CAVS’s | yours |
A single organization can mix both: repository A on managed storage, B on AWS S3, C on MinIO. The invoice separates each.
Deletion
Section titled “Deletion”Deleting a repository or an organization drops the metadata immediately and queues the bytes for garbage collection. Managed objects become unrecoverable once collected. Take a snapshot or download what you need first.
- Bring Your Own S3 — keep the bytes in your account.
- Deduplication explained — why physical ≪ logical.
- Lifecycle & maintenance — GC, repack, compaction.

