A lightweight, modular, backendβonly billing engine built with FastAPI, SQLAlchemy, and a clean serviceβlayer architecture. It ingests usage events, aggregates them, prices them, and generates invoices β all without any frontend or dashboard.
This project is ideal for demonstrating backend engineering skills such as:
Record usage events (e.g., API calls, storage, workflows)
Daily usage aggregation (group + sum raw events)
Pricing engine (simple perβunit pricing, easily extendable)
Invoice preview (estimate charges before billing period ends)
Invoice generation (creates real invoice records)
Clean service layer (routers β services β models)
Backgroundβsafe aggregation (manual or scheduled)
SQLite for simplicity (swap for Postgres easily)
billing_engine/
β
βββ app/
β βββ routers/
β β βββ usage.py
β β βββ invoice.py
β β βββ aggregator.py
β βββ services/
β β βββ usage_service.py
β β βββ invoice_service.py
β β βββ aggregator_service.py
β βββ models.py
| βββ aggregator.py
| βββ pricing.py
β βββ schemas.py
β βββ deps.py
β βββ database.py
β
βββ tests.py/
| βββ conftest.py
| βββ test_aggregator.py
| βββ test_api.py
| βββ test_invoice.py
| βββ test_usage.py
βββ scheduler.py
βββ main.py
βββ worker.py
βββ README.md
βββ LICENSE.md
βββ CONTRIBUITING.md
python -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
pip install -r requirements.txt
On Windows (WSL recommended):
redis-server
Start the FastAPI server
uvicorn main:app --reload
Your API is now live at:
http://127.0.0.1:8000
Swagger UI:
http://127.0.0.1:8000/docs
In a new terminal:
rq worker
In another terminal:
python scheduler.py
POST /usage
Example:
POST /aggregate/run
GET /invoice/preview/{customer_id}
POST /invoice/{customer_id}
Usage Ingestion Raw events are stored exactly as they happen:
customer
metric
units
timestamp
This keeps ingestion fast and appendβonly.
A background job periodically:
fetches raw events
groups them by metric + customer
sums units
writes aggregated rows
This reduces billing load and keeps invoices fast.
A simple perβunit pricing dictionary:
PRICING = {
"api_calls": 0.0005,
"storage_gb": 0.25,
"workflows": 0.10,
}
You can easily extend this to:
tiered pricing
free allowances
perβcustomer overrides
Reads aggregated usage so far and returns:
usage totals
estimated amount
billing window
No DB writes.
Reads aggregated usage, calculates the final amount, and writes an invoice row.
FastAPI β API framework
SQLAlchemy β ORM + models
SQLite β local development DB
RQ (Redis Queue) β background worker
Redis β job queue backend
Uvicorn β ASGI server
UsageEvent Raw usage events.
AggregatedUsage Daily totals per metric.
Invoice Final billed amounts.