A production-ready, event-driven cloud storage platform with integrated billing, built with FastAPI, React, and modern cloud services.
Live demo: cloud-storage-billing-engine.vercel.app
Frontend uploads directly to object storage via Pre-signed POST, bypassing the API bottleneck for optimal performance and scalability. Uses MinIO locally and Cloudflare R2 in production β both speak the S3 API, so the same client code works against either.
Uses a Redis-backed worker to process storage metrics asynchronously, ensuring accurate billing based on actual file sizes rather than client-reported data.
Strict path-based separation ensuring users can never access each other's objects, with JWT-based authentication and authorization.
Nexus Storage provides a complete cloud storage solution featuring:
- Direct S3-Compatible Uploads: Pre-signed URLs for efficient, serverless file uploads
- Real-Time Metering: Event-driven usage tracking with Redis and background workers
- Secure Multi-Tenancy: Isolated user storage with Supabase authentication
- Integrated Billing: Razorpay-powered payment processing with usage-based pricing
- Modern Frontend: React TypeScript dashboard with real-time updates
- RESTful API: FastAPI backend with comprehensive documentation
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β React β β FastAPI β β MinIO β
β Frontend βββββΊβ Backend βββββΊβ (S3-Compat, β
β (Vite) β β + Worker β β local Docker) β
β β β (Python) β β β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ
β Supabase β β Redis β
β Auth & DB β β Metering β
βββββββββββββββββββ βββββββββββββββββββ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β React β β FastAPI β β Cloudflare R2 β
β Frontend βββββΊβ Backend βββββΊβ (S3-Compat) β
β (Vercel) β β + Worker β β Storage β
β β β (Render) β β β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ
β Supabase β β Upstash β
β Auth & DB β β Redis β
βββββββββββββββββββ βββββββββββββββββββ
Note on the worker: the metering worker (
app/worker.py) was originally deployed as a separate Render Background Worker service. Render's free tier doesn't support that service type, so the worker loop now runs as a daemon thread launched fromapp/main.pyon FastAPI startup β it rides along with the web service instead of needing its own (paid) deployment. Locally, you can still run it either way (see below).
- FastAPI - High-performance async web framework
- Supabase - Authentication, database, and real-time subscriptions
- MinIO (local dev) / Cloudflare R2 (production) - S3-compatible object storage
- Redis - Event-driven metering and background processing (self-hosted locally, Upstash in production)
- Razorpay - Payment processing and billing
- Pydantic - Data validation and settings management
- React 18 - Modern UI framework with hooks
- TypeScript - Type-safe development
- Vite - Fast build tool and dev server
- Tailwind CSS - Utility-first styling
- React Query - Powerful data fetching and caching
- Supabase JS - Client-side authentication
- Vercel - Frontend hosting
- Render - Backend API + in-process worker
- Cloudflare R2 - Production object storage
- Upstash - Managed Redis for metering
- Supabase - Managed Postgres + Auth
app/main.py- FastAPI application with REST endpoints; also launches the metering worker as a background thread on startupapp/auth.py- JWT validation using Supabase JWKsapp/storage.py- S3-compatible client (MinIO/R2) and presigned URL generationapp/metering.py- Redis event logging for upload trackingapp/worker.py- Worker loop for usage calculation; run standalone locally, or imported and threaded bymain.pyin productionapp/billing_sync.py- Razorpay billing synchronizationapp/config.py- Environment configuration management
src/components/files/- File upload and management UIsrc/components/billing/- Billing dashboard and payment flowsrc/lib/supabase.ts- Supabase client configurationsrc/lib/api.ts- Axios client with JWT interceptorssrc/hooks/useAuth.ts- Authentication state management
- Python 3.11+
- Node.js 18+
- Docker (for local MinIO/Redis)
- Git
# Clone and setup
git clone <repository-url>
cd Cloud_storage_billing_engine
# Python environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
# Environment configuration
cp .env.example .env
# Edit .env with your local service credentials (see Configuration below)# MinIO (Storage) - local S3-compatible storage for dev
docker run -d -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio server /data --console-address ":9001"
# Redis (Metering)
docker run -d -p 6379:6379 redis/redis-stack
# FastAPI Backend (this also starts the worker thread automatically on startup)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000The worker is started automatically inside the FastAPI process. If you want to run it standalone instead (e.g. to debug it in isolation), you can still do so:
python app/worker.pyJust note that running it both ways at once will double-process events.
cd frontend
npm install
cp .env.example .env.local
# Edit .env.local with Supabase credentials
npm run devAccess Points (local):
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- MinIO Console: http://localhost:9001
The backend talks to storage over the S3 API via MINIO_* settings β locally these point at your MinIO container, in production they point at your Cloudflare R2 bucket.
# Object Storage (MinIO locally, Cloudflare R2 in production)
# Local (MinIO):
MINIO_ENDPOINT=http://localhost:9000
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
STORAGE_BUCKET_NAME=nexus-storage
# Production (Cloudflare R2) β set these instead on Render:
# MINIO_ENDPOINT=https://<your-account-id>.r2.cloudflarestorage.com
# MINIO_ROOT_USER=<R2 access key id>
# MINIO_ROOT_PASSWORD=<R2 secret access key>
# STORAGE_BUCKET_NAME=<your R2 bucket name>
# Supabase Configuration
SUPABASE_JWT_SECRET=your-jwt-secret
SUPABASE_PROJECT_ID=your-project-id
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Redis Configuration (Upstash in both dev and prod, or local Redis for dev)
UPSTASH_REDIS_REST_URL=your-redis-url
UPSTASH_REDIS_REST_TOKEN=your-redis-token
# Razorpay Configuration
RAZORPAY_KEY_ID=your-razorpay-key-id
RAZORPAY_KEY_SECRET=your-razorpay-key-secret
RAZORPAY_TEST_SUB_ID=your-test-subscription-idVITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key- Frontend requests presigned upload URL from
/upload-url - Backend generates a presigned POST URL against the configured storage backend (MinIO locally, R2 in production) with user isolation
- Frontend uploads directly to storage (bypassing the API)
- Backend logs upload event to Redis queue
- Worker thread (running inside the backend process) processes the event, gets actual file size from storage
- Worker updates Supabase usage database
- Frontend displays usage from
/billing/usageendpoint - User initiates payment via Razorpay checkout
- Backend creates Razorpay order with calculated amount
- Razorpay processes payment and returns verification data
- Backend verifies payment signature and resets usage
POST /upload-url- Get presigned upload URLGET /files- List user filesGET /download/{filename}- Get download URLDELETE /files/{filename}- Delete file
GET /billing/usage- Get usage and billing dataPOST /billing/pay- Create Razorpay payment orderPOST /billing/verify- Verify payment completion
GET /health- Health check endpoint
- JWT Authentication - Supabase-based token validation
- Multi-Tenant Isolation - Path-based user separation
- Pre-signed URLs - Time-limited, secure upload/download access
- Payment Verification - HMAC signature validation for Razorpay
- CORS Protection - Configurable origin restrictions
- Direct-to-Storage Uploads - No API bottleneck for file transfers
- Async Metering - Background thread processing for usage calculations, no separate paid worker service needed
- Redis Caching - Fast event queuing and processing
- React Query - Intelligent caching and background refetching
- Lazy Loading - Component-based code splitting
# Run with test environment
pytest tests/cd frontend
npm run test
npm run test:e2e # Playwright end-to-end testsCurrent live setup:
- Frontend β Vercel
- Backend API + worker thread β Render (free tier Web Service)
- Object storage β Cloudflare R2
- Redis β Upstash
- Auth & DB β Supabase
- Payments β Razorpay
- Configure production Supabase project
- Set up Cloudflare R2 bucket for production storage
- Configure production (Upstash) Redis instance
- Set up Razorpay production credentials
- Run metering worker in-process (Render free tier has no separate background worker service)
- Update CORS origins for production domain (currently
*β tighten before scaling up) - Enable HTTPS and security headers
- Set up monitoring and logging
- Configure backup strategies
- Point
MINIO_ENDPOINTat your R2 S3 API endpoint (https://<account-id>.r2.cloudflarestorage.com) and setMINIO_ROOT_USER/MINIO_ROOT_PASSWORDto your R2 access key ID / secret access key. No code changes are needed since R2 is S3-compatible. - The worker no longer needs its own Render service β it's launched as a daemon thread in
main.py's FastAPI startup event, so a single free-tier Web Service handles both API traffic and metering.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.