Problem Statement
Apps need more than "mint a presigned URL" — a real product needs a managed file service: multiple tenants/buckets with their own access keys, both admin (dashboard) and programmatic (API key) auth, presigned uploads/downloads, streaming for files too big to buffer in memory, metadata, and caching so hot files are cheap to serve. Rolling all of that per-app is wasteful and error-prone.
Proposed Solution
Storex is a production-ready, self-hostable file storage and management service. Built on TypeScript + Express + MongoDB with Cloudflare R2 (S3-compatible) for object storage, it implements domain-driven design and ships the full feature set: multi-tenant buckets, dual auth, presigned URLs, large-file streaming, and multi-level caching — plus a companion frontend.
Full Solution Details
- File operations — upload, download, streaming, metadata management.
- Bucket management — a multi-tenant bucket system with public/private keys per bucket.
- Auth — JWT for admin/dashboard access and API keys for programmatic access.
- Presigned URLs — secure direct-to-R2 upload/download with configurable expiration.
- File streaming — direct streaming of large files without buffering them in memory.
- Caching — a multi-level caching layer for performance.
- Frontend — a companion management UI (storex-frontend).
Technical Documentation
Node + TypeScript + Express on MongoDB (Mongoose), with Cloudflare R2 as the S3-compatible object store. The codebase follows domain-driven design with middleware composition, express-validator with custom rules, JWT + API-key authentication, and a multi-tier cache. The two engineering highlights: (1) streaming large files directly rather than reading them into memory (so a multi-GB download doesn't OOM the process), and (2) a multi-tenant bucket model where each bucket carries its own public/private keys, enabling per-tenant isolation and public-vs-private access without separate deployments. Build uses the TypeScript compiler with tsc-alias for path resolution.
Tech Stack
TypeScript, Node.js, Express, MongoDB/Mongoose, Cloudflare R2 (S3-compatible), JWT, API keys, express-validator, multi-level caching; companion React frontend.
System Design
Admin (JWT) ─┐ ┌─ presigned PUT/GET (R2, configurable TTL)
├─► Storex API (Express, DDD)
App (API key)┘ ├── bucket mgmt (multi-tenant, public/private keys)
├── file ops: upload · download · stream (no mem buffering)
├── metadata (MongoDB)
└── multi-level cache
│
▼
Cloudflare R2 (S3-compatible object storage)
Smart Architectural Decisions
- Stream, don't buffer. Serving large files via streaming instead of loading them into memory is the decision that separates a toy uploader from a production storage service — it bounds memory regardless of file size.
- Multi-tenant buckets with per-bucket keys. Modeling tenancy at the bucket level (public/private keys per bucket) means one deployment serves many apps with isolation — the design that lets Storex back his other projects (Dondie uses it).
- Dual auth (JWT + API key). Separating human/dashboard access (JWT) from machine access (API keys) is the correct, conventional split for a service consumed both ways.
- DDD + middleware composition. Organizing by domain with composable middleware keeps a feature-rich service maintainable.
- R2 over AWS. Cloudflare R2 (no egress fees) is a cost-aware object-store choice for a service meant to serve files cheaply.
Impacts
A reusable, production-grade storage backend that any of the author's apps can stand on — multi-tenant, streaming-capable, cached, and secured two ways — turning "file handling" into a solved, shared service rather than per-app plumbing.
Demonstrated Skills
Domain-driven backend architecture; object-storage integration (Cloudflare R2, presigned URLs); memory-safe large-file streaming; multi-tenant system design (bucket isolation, public/private keys); dual authentication (JWT + API key); multi-level caching; TypeScript/Express/MongoDB; building reusable internal platform services.