Skip to content

Privacy & data

A value deleted or overwritten at time T is gone from every copy TapeDB keeps by T + retention: the local log, R2 log segments and older snapshots. That holds in a quiet workspace too. You are the controller of the data; TapeDB runs in your Cloudflare account and Cloudflare is your processor.

defineTapeDB({ schema, migrations, retention: { days: 30 } }); // default 30, at least 2
Where What How long
Durable Object SQLite, one per workspace Your models’ rows Until deleted
Each write’s operations and time. Who made a row write is not recorded Half the retention (15 days by default)
Retry receipts: random client transaction id, sequence, time, and an operation hash while recent Id, sequence and time for the workspace lifetime; hash removed after half the retention. Superseded R2 copies leave within the full retention
The file index: path, size, content type and uploader Until the file is deleted
R2 DATA bucket Log segments, snapshots, a manifest Superseded copies leave within the retention
R2 FILES bucket Uploaded bytes Deleted with the file, at once
Socket state A connected client’s subject, role, subscriptions, presence and topics, in memory and, past 12 KiB, in the Durable Object While the socket is open
Claim limiter A token count per HMAC of a caller’s IP or subject, never the values Until the bucket refills, a minute by default
Broadcast Messages Not stored

Receipts contain no row values or writer identity. Storage grows by one small receipt per transaction with a client id. Use random transaction ids, not user ids. Workspace erasure removes the receipts too.

Claim tokens never appear in a URL: HTTP requests carry them in Authorization, WebSocket upgrades in Sec-WebSocket-Protocol. If you log request headers in Cloudflare, exclude those two. Use an opaque user id as the claim’s sub, not an email address.

  • Durable Object point-in-time recovery. Cloudflare keeps 30 days of restorable history for every SQLite-backed Durable Object. TapeDB never restores from it, but the effective bound is the greater of the retention and 30 days. That is why the default retention is 30 days.
  • R2 bucket locks. A lock rule on the DATA or FILES bucket stops TapeDB from deleting what it covers. Don’t add one to TapeDB’s buckets.
Request How
Access and portability db.$export() or tapedb export --workspace <id> streams every row and file entry the claim may read, through the read rules. See Export.
Rectification Update the rows. Old values leave the history within the retention.
Erasure of a person Delete or overwrite their rows and delete their files with db.$files.delete(path), which removes the bytes at once. The old values leave the history within the retention, and Cloudflare’s recovery within 30 days.
Erasure of a workspace tapedb erase --workspace <id> --confirm <id>, or DELETE /engine/workspaces/:id with an owner claim, deletes the R2 history, the files and the Durable Object storage. The workspace answers 410 afterwards.

By default Cloudflare places each workspace’s Durable Object near its first request, and R2 buckets wherever they were created. tapedb init --jurisdiction eu keeps the Durable Objects and both buckets in Cloudflare’s EU jurisdiction, and tapedb deploy refuses a config where the two disagree. Choose it before the first deploy: changing it later addresses new, empty workspaces. Cloudflare remains the processor, so your transfer assessment and Cloudflare’s data processing addendum still apply.