Object versioning for Cloudflare R2
Add version history to an existing R2 bucket without changing how anything reads from it. Every put, delete and restore keeps an immutable version.
npm i @ver2/sdk
How it works
Use it from code or the terminal
import { createVer2 } from "@ver2/sdk";
import { S3ObjectStore } from "@ver2/sdk/s3";
const ver2 = createVer2({ store: new S3ObjectStore({ bucket, accountId, credentials }) });
const { versionId } = await ver2.put("docs/report.pdf", bytes);
await ver2.versions.list("docs/report.pdf");
await ver2.versions.restore("docs/report.pdf", versionId);Honest guarantees
veR2 guarantees what R2 lets it guarantee and documents the rest. Read the details.
| ✅ | Concurrent veR2 writers to one key | Serialized; losers get ConcurrencyConflict |
| ✅ | A direct write racing a veR2 write | Detected; never silently clobbered |
| ✅ | Crash mid-operation | Rolled forward/back from evidence, or flagged OperationIncomplete |
| ✅ | Version integrity | SHA-256 verified on download |
| ⚠️ | Direct deletes (outside veR2) | Cannot be prevented or undone: R2 ignores delete conditions |
| ⚠️ | Hot keys | R2 allows about 1 write/s per key; expect 429s on rapid rewrites |
| ⚠️ | Large objects | Bodies are buffered in memory for now; streaming comes later |
Start keeping history
Install the SDK, point it at your bucket, and every write is versioned.