From cdf2295ef6445723b855f5aae84ce6370386301c Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Sun, 10 May 2026 00:07:39 +0700 Subject: [PATCH] docs(canvas): correct CF DO limits in resize doc and plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier docs assumed a 1 GB per-DO storage cap. Actual May 2026 free-tier limits per the CF DO docs: - 10 GB per Durable Object - 5 GB per account (the real Free-tier ceiling) - 2 MB per BLOB row - 1,000 req/sec soft cap per DO Practical effect: canvas can grow to ~70,000 × 70,000 on Free (was previously documented as ~32K × 32K). Existing 64 KB CHUNK_BYTES is well-suited: clustered writes (single pixels + image patches) minimize read-modify-write amplification; bigger chunks would only help uniform-random writes which isn't rplace's workload. No code change. Just doc accuracy. --- docs/canvas-resize-procedure.md | 15 ++++++++++----- .../phase-01-storage-foundation.md | 9 +++++++++ plans/260509-2309-canvas-on-do-storage/plan.md | 4 +++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/canvas-resize-procedure.md b/docs/canvas-resize-procedure.md index 60fa100..754d36f 100644 --- a/docs/canvas-resize-procedure.md +++ b/docs/canvas-resize-procedure.md @@ -38,14 +38,19 @@ needed. - **Aspect ratio change** (non-square) is fine. The 1-D byte-layout (`y * CANVAS_WIDTH + x`) still holds. Just make sure clients pull the new constants too — frontend reads them from the same module. -- **Storage cap.** SQLite-backed DO storage is 1 GB on the Free plan. - A 1-byte-per-pixel canvas fits up to roughly **32,768 × 32,768** - before hitting that ceiling. +- **Storage caps (Cloudflare Free plan, 2026).** + - Per Durable Object: **10 GB** (would allow ~100,000 × 100,000) + - Per Account: **5 GB** (the real ceiling on Free) + - At 1 byte per pixel, the practical free-tier ceiling is roughly + **70,000 × 70,000 pixels** (≈4.9 GB). + - SQLite BLOB row cap is **2 MB**; our 64 KB `CHUNK_BYTES` has 32× headroom + so resizing never touches that limit. ## Free-tier monitoring After resize, watch: - Cloudflare Workers requests/day (free cap: 100,000) -- Durable Object storage size (free cap: 1 GB per DO) +- Durable Object storage (free caps: 10 GB per DO, 5 GB per account) +- Per-DO request rate (soft cap: 1,000 req/sec) -Both visible on the Cloudflare dashboard for the rplace project. +All visible on the Cloudflare dashboard for the rplace project. diff --git a/plans/260509-2309-canvas-on-do-storage/phase-01-storage-foundation.md b/plans/260509-2309-canvas-on-do-storage/phase-01-storage-foundation.md index 78b150f..62477c0 100644 --- a/plans/260509-2309-canvas-on-do-storage/phase-01-storage-foundation.md +++ b/plans/260509-2309-canvas-on-do-storage/phase-01-storage-foundation.md @@ -39,6 +39,15 @@ export const CHUNK_BYTES = 65536; // 64 export const CHUNK_COUNT = Math.ceil(TOTAL_PIXELS / CHUNK_BYTES); // 256 ``` +**Why 64 KB chunks (informed by actual CF DO limits, May 2026):** +- BLOB row cap is **2 MB** → `CHUNK_BYTES` could be up to ~2 MB; we use 64 KB (32× under). +- Storage caps are **10 GB / DO** and **5 GB / account** (Free) → 16 MB canvas + is ~300× under either cap; resize to ~70K×70K is feasible on Free. +- Soft request cap is **1,000 req/sec / DO** → hobby workload is 1‰ of this. +- Smaller chunks minimize read-modify-write amplification on **clustered** writes + (single placements + image patches), which is rplace's actual workload pattern. + Bigger chunks would only help uniform-random writes — not a real workload here. + Schema (created in DO constructor via `sql.exec` if not exists): ```sql diff --git a/plans/260509-2309-canvas-on-do-storage/plan.md b/plans/260509-2309-canvas-on-do-storage/plan.md index 3301444..80d319a 100644 --- a/plans/260509-2309-canvas-on-do-storage/plan.md +++ b/plans/260509-2309-canvas-on-do-storage/plan.md @@ -73,7 +73,9 @@ Phase order is strict: 1 → 2 → 3 → 4 → 5. Each phase blocks the next. | Test rewrite scope creep | Low | Time-box testcontainers→DO test rewrite to 4h; cut e2e if needed | | Migration corrupts canvas | High | Keep Upstash data 7 days post-migration as rollback | | DO single-region latency regression | Low | Same as today's Upstash (single region) — no change | -| Storage billing exposure if canvas grows | Med | Monitor; current 16 MB << 1 GB threshold | +| Storage exposure if canvas grows | Low | Per-DO 10 GB / per-account 5 GB on Free; current 16 MB has 300× headroom | +| BLOB row size cap (2 MB) | None | `CHUNK_BYTES = 64 KB` has 32× headroom from this limit | +| Per-DO 1,000 req/sec soft cap | None | Hobby load is ~1 req/sec; edge cache absorbs `/api/canvas` | ## Rollback Plan