Skip to content

Usage ledger: daily per-workspace usage + cost, monthly CSV - #92

Merged
leorfer23 merged 1 commit into
mainfrom
usage-ledger
Oct 14, 2026
Merged

leorfer23 merged 1 commit into
mainfrom
usage-ledger

Conversation

@leorfer23

Copy link
Copy Markdown
Contributor

What

workspace_usage_daily records what each workspace cost per UTC day, one row per metric, so an operator can see daily and monthly usage and invoice from it. The existing "Cost by workspace" view only estimates the current window, and its storage is point-in-time and misses most of R2.

How

  • Nightly rollup (00:00 UTC, for the day that just ended), idempotent:
    • serving requests (analytics_events)
    • job runs + duration (job_runs)
    • LLM tokens + real cost (agent_usage_events, BYO-key calls excluded)
    • non-LLM AI (ai_usage_events)
    • storage measured by listing R2. Every write path counts: drafts, thumbnails, inbox mail, connection caches, logos, not only assets/datasets/blobs. Soft-deleted and personal artifacts are left unattributed.
  • Live counters: recipients of artifact emails (sendArtifactEmail, which every customer send path uses) and browser seconds (screenshots, slide export, pilot verify).
  • Cost at Cloudflare list price: R2 $0.015/GB-mo, Browser Rendering $0.09/h, Email $0.35/1k, Workers requests/CPU from cf-pricing.ts. AI uses the real provider cost. Storage is priced per day, so a month sums to GB-months. Account-wide free allowances are not split across workspaces.
  • Admin:
    • "Usage ledger" view: this month so far plus last month, per workspace.
    • GET /v1/admin/usage.csv?month=YYYY-MM[&by=day]
    • POST /v1/admin/usage/rollup {day} to backfill. It only measures storage for yesterday or today.

Schema

New migration 0010_workspace_usage_daily.sql, documented in SCHEMA.md §12. ON DELETE CASCADE on workspace: deleting a workspace drops its ledger, so export before deleting.

Checks

  • npm run typecheck ✓
  • check:migrations ✓
  • tooling/scripts/ci-check-fast.sh ✓ (incl. gitleaks + customer names)
  • npm test: 5061 tests, all green after updating 3 scheduling-email assertions for the new recipients field
  • New tests/unit/usage-ledger.test.ts runs the real migrations in Miniflare D1/R2 (attribution, day bounds, BYO exclusion, idempotency, live counters).
  • Pre-push hook ✓

Deploy notes

Needs wrangler d1 migrations apply --remote before the version goes live. After deploy, backfill the current month's event metrics with POST /v1/admin/usage/rollup per day. Storage history starts the first night after deploy.

🤖 Generated with Claude Code

workspace_usage_daily records what each workspace cost per UTC day per metric, so
an operator can see daily and monthly usage and invoice from it.

- Nightly rollup (00:00 UTC, for the day that ended): serving requests, job runs +
  duration, AI tokens (BYO-key calls excluded) and non-LLM AI from the existing
  event tables; storage measured by listing R2, so drafts, thumbnails, inbox mail
  and connection caches count, not only assets/datasets/blobs.
- Live counters: artifact email recipients (sendArtifactEmail) and browser
  seconds (screenshots, slide export, pilot verify).
- Cost at Cloudflare list price (R2 $0.015/GB-mo, Browser $0.09/h, Email
  $0.35/1k) or real provider cost for AI; storage priced per day so a month sums
  to GB-months.
- Admin: "Usage ledger" view (this month + last month), GET
  /v1/admin/usage.csv?month=YYYY-MM[&by=day], POST /v1/admin/usage/rollup to
  backfill a day.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leorfer23
leorfer23 merged commit 3ebfafd into main Oct 14, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant