BriterWrite. Publish. Own it.

Documentation

Storage & Uploads

Disk-aware provisioning: how Briter senses free disk, sets an upload cap, enforces it, and reports used/cap/free on the dashboard.

Storage & Uploads

Briter stores processed images on the local data volume and enforces a provisioned upload cap so a single instance can't fill the disk. This page covers the cap, how it's sensed and enforced, and where usage is reported. For the image pipeline (variants, EXIF stripping, formats), see Images.

The upload cap

Every upload counts against a byte cap, BRITER_UPLOAD_STORAGE_LIMIT_BYTES (default 500 MB = 524288000). The cap is a self-imposed budget, independent of the physical disk size — it protects the host even when there's plenty of free space.

The setup wizard senses the real free disk at install time and proposes a sensible cap; you can adjust it later in Settings. The cap is stored in config.json and can be overridden by the environment variable (see Configuration Reference).

Enforcement

Enforcement lives in UploadImageService (lib/uploads/image-upload-service.ts), backed by helpers in lib/uploads/budget.ts:

  • Hard cap: an upload that would push total upload size over the cap is rejected with UploadLimitError.
  • 95% soft cap: an upload that would cross 95% of the cap is also rejected (isNearCapacity flags usage >= floor(cap * 0.95)), with the message "Upload storage is near capacity (95% soft cap)." This leaves headroom rather than letting the very last byte fill the budget.

Current usage is computed by summing the size of every file under the upload root, recursively (computeDirectorySize), so images nested in per-post subfolders are counted correctly.

Disk sensing

Briter also reports the physical headroom of the volume that backs uploads, separately from the self-imposed cap. senseDiskUsage() (lib/uploads/disk-usage.ts) uses Node's fs.statfsSync to read total, free, and used bytes for the filesystem holding the upload root. Disk sensing is informational and never fatal — if it fails, Briter returns null for the disk figures and carries on.

Where usage is reported

The dashboard shows a storage bar. The data comes from GET /api/uploads/usage, which returns:

Field Meaning
usedBytes Bytes currently consumed by uploads.
capBytes The provisioned cap (BRITER_UPLOAD_STORAGE_LIMIT_BYTES).
disk Physical totalBytes / freeBytes / usedBytes of the data volume, or null if sensing failed.

So the dashboard can show used vs. cap (your budget) alongside free disk (actual headroom).

Freeing space

Briter does not yet ship a media-library manager. To reclaim space, delete the variant files and the corresponding manifest under the upload root (storage/uploads/posts/<slug>/); usage recomputes from the filesystem on the next check.

Object storage

The Constitution provides for images on either local disk or an S3-compatible bucket (Cloudflare R2, Backblaze B2, MinIO, AWS S3). The disk-aware cap described here governs the local-disk path, which is what ships today; see the Roadmap for the storage-provider abstraction.