πŸ” BillingWatch

April 4, 2026 Β· View on GitHub

PyPI version

πŸ” BillingWatch β€” Self-Hosted Stripe Billing Anomaly Detector

Python 3.9+ FastAPI License: MIT Tests: Passing Self-Hosted Stripe Docker Deploy on Railway Deploy to Render

Catch billing bugs, dunning failures, and fraud before they hit your churn metrics β€” entirely on your own machine.

BillingWatch listens to your Stripe webhook stream and runs 7 real-time anomaly detectors against every event. Duplicate charges, revenue drops, fraud spikes, silent subscription lapses β€” detected and alerted in seconds. No cloud subscription. No SaaS fees. No data leaving your server.


πŸ€” Who Is This For?

  • SaaS founders who want billing QA without paying for another tool
  • Indie developers using Stripe who've been burned by silent billing failures
  • Privacy-conscious teams who don't want their revenue data on someone else's server
  • DevOps engineers who need webhook observability without a full APM stack

✨ What It Detects

DetectorWhat It CatchesSeverity
charge_failure_spikeFailure rate > 15% over 1 hour β€” gateway issue or card BIN attackπŸ”΄ High
duplicate_chargeSame customer charged twice within 5 min β€” idempotency bug🚨 Critical
fraud_spikeDispute/chargeback rate exceeds threshold β€” active fraud campaign🚨 Critical
negative_invoiceInvoice total < 0 β€” broken promo stacking or discount bug🟑 Medium
revenue_dropMRR > 15% below 7-day rolling average β€” silent churn or billing breakπŸ”΄ High
silent_lapseActive subscription with no successful payment in period🟑 Medium
webhook_lagEvents arriving > 10 min late β€” Stripe delivery degradation🟒 Low

When a detector fires, BillingWatch sends alerts via email and/or outbound webhook.


πŸ†š Why Not Just Use [Datadog / Baremetrics / Stripe Radar]?

BillingWatchDatadogBaremetricsStripe Radar
CostFree (self-hosted)5+/mo29+/moBuilt-in (limited)
Your data leaves your server?❌ Neverβœ… Yesβœ… Yesβœ… Yes
Custom anomaly logicβœ… Full controlPartial❌❌
Stripe-specific detectorsβœ… 7 built-in❌ General❌ Metrics only❌ Fraud only
Self-hostableβœ… Yes❌❌❌
Alert destinationsEmail + webhookManyEmailDashboard only

BillingWatch is for makers who want billing QA (not analytics) with zero SaaS lock-in.


πŸš€ Quick Start

⚑ One-Click Deploy on Railway

Deploy on Railway

No local setup required. Railway will prompt for your STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET on deploy.

☁️ One-Click Deploy on Render

Deploy to Render

Free tier available. Render will read render.yaml automatically and prompt for env vars on first deploy.

Requirements

  • Python 3.9+
  • A Stripe account (test mode is fine)
  • Stripe CLI (optional β€” for local webhook forwarding)

Install

git clone https://github.com/rmbell09-lang/BillingWatch.git
cd BillingWatch
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configure

cp .env.example .env

Minimum config for local dev:

STRIPE_SECRET_KEY=sk_test_PLACEHOLDER
STRIPE_WEBHOOK_SECRET=dev
APP_ENV=development
LOG_LEVEL=DEBUG
PORT=8000

Note: STRIPE_WEBHOOK_SECRET=dev bypasses signature verification. Never use in production.

Run

source .venv/bin/activate
STRIPE_WEBHOOK_SECRET=dev uvicorn src.api.main:app --reload --port 8000

Verify

curl http://localhost:8000/health
# {"status": "ok"}

curl http://localhost:8000/webhooks/detectors
# Lists all 7 registered detectors

Send a Test Event

curl -s -X POST localhost:8000/webhooks/stripe \
  -H 'Content-Type: application/json' \
  -H 'Stripe-Signature: dev' \
  -d '{
    "id": "evt_test_001",
    "type": "charge.failed",
    "created": 1709599200,
    "data": {"object": {"id": "ch_001", "customer": "cus_001", "amount": 2999}}
  }'

Or with Stripe CLI for real test events:

stripe listen --forward-to localhost:8000/webhooks/stripe
stripe trigger charge.failed

πŸ“‘ API Reference

EndpointMethodDescription
/healthGETHealth check
/docsGETInteractive Swagger UI
/webhooks/stripePOSTStripe event ingestion
/webhooks/alertsGETRecent anomaly alerts
/webhooks/detectorsGETRegistered detectors list
/metricsGETtotal_events, events_by_type, uptime_seconds, detector_count
/metrics?window_hours=NGETRolling window metrics (0.1–168h)
/metrics/detectorsGETPer-detector alert counts + severity
/metrics/recent-eventsGETMost recent webhook events

πŸ—οΈ Architecture

Stripe Webhooks
      β”‚
      β–Ό
 FastAPI (port 8000)
      β”‚
      β”œβ”€β”€β”€ Signature Validation (Stripe-Signature header)
      β”‚
      β”œβ”€β”€β”€ Event Store (SQLite / PostgreSQL)
      β”‚
      └─── Detector Pipeline (parallel evaluation)
                β”‚
                β”œβ”€β”€β”€ charge_failure_spike
                β”œβ”€β”€β”€ duplicate_charge
                β”œβ”€β”€β”€ fraud_spike
                β”œβ”€β”€β”€ negative_invoice
                β”œβ”€β”€β”€ revenue_drop
                β”œβ”€β”€β”€ silent_lapse
                └─── webhook_lag
                          β”‚
                          β–Ό
                   Alert Dispatch
                   β”œβ”€β”€β”€ Email (SMTP)
                   └─── Outbound Webhook

Stack: Python 3.9+ Β· FastAPI Β· SQLite (dev) / PostgreSQL (prod) Β· Redis Β· APScheduler Β· Stripe SDK


πŸ§ͺ Running Tests

source .venv/bin/activate
pytest tests/ -v

# Detector unit tests only
pytest tests/test_detectors/ -v

# With coverage
pytest tests/ --cov=src --cov-report=term-missing

πŸ”§ Adding a Custom Detector

Extend BaseDetector from src/detectors/base.py:

from .base import Alert, BaseDetector

class MyDetector(BaseDetector):
    name = "my_detector"

    def process_event(self, event: dict):
        if event.get("type") == "some.stripe.event":
            return [Alert(
                detector=self.name,
                severity="medium",
                title="Something happened",
                message="Details here"
            )]
        return []

Register it in src/api/main.py startup. Done.


πŸ”’ Production Deployment

See docs/production-setup.md for:

  • Stripe live key setup via macOS Keychain
  • Cloudflare Tunnel for webhook exposure (no open ports)
  • PostgreSQL + Redis configuration
  • Pre-launch security checklist

Never put live Stripe keys in .env files. Use Keychain or a secrets manager.


πŸ“ Project Structure

BillingWatch/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ api/               # FastAPI app + routes
β”‚   β”œβ”€β”€ detectors/         # 7 anomaly detectors + BaseDetector
β”‚   β”œβ”€β”€ storage/           # SQLite/Postgres event persistence
β”‚   β”œβ”€β”€ workers/           # Async processing + APScheduler
β”‚   β”œβ”€β”€ alerting/          # Email + webhook alert delivery
β”‚   β”œβ”€β”€ models/            # SQLAlchemy models + Pydantic schemas
β”‚   └── stripe_client.py   # Stripe SDK wrapper
β”œβ”€β”€ tests/                 # Unit + E2E tests
β”œβ”€β”€ docs/                  # Setup guides + spec
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml
└── README.md

πŸ—ΊοΈ Roadmap

v1.1 (In Progress)

  • πŸ“§ Email Digest β€” daily/weekly anomaly summary (endpoint live, SMTP config needed)
  • ☁️ Render.com 1-Click Deploy β€” render.yaml + deploy button βœ…
  • πŸ” Webhook Event Explorer UI β€” searchable, filterable event log

v1.2 (Planned)

  • πŸ“Š Grafana Dashboard β€” pre-built anomaly trend dashboard
  • πŸ”” Slack/Discord Alerts β€” native integrations
  • πŸ§ͺ Test Mode Replay β€” replay historical events without live webhooks


BillingWatch fills the gap between expensive SaaS platforms and doing nothing:

ToolTypeCostWhy BillingWatch Instead
DatadogFull observability$5+/moGeneral-purpose APM, no Stripe-specific detectors
BaremetricsSaaS analytics$29+/moAnalytics dashboards, not real-time anomaly alerts
Stripe RadarFraud detectionBuilt-inCard fraud only β€” no dunning failures, duplicate charges, or webhook lag
SentryError monitoring$26+/moCode errors, not billing events
ChartMogulRevenue analytics$100+/moHistorical charts, not real-time detection
LagoOpen-source billingSelf-hostedFull billing system β€” BillingWatch monitors Stripe, not replaces it

BillingWatch is free, self-hosted, and purpose-built for Stripe billing QA. One webhook endpoint. Seven detectors. Zero SaaS fees.

Also useful for: stripe monitoring Β· stripe webhook monitoring Β· billing anomaly detection Β· SaaS billing monitoring Β· self-hosted stripe monitor Β· payment failure alerts Β· subscription billing QA Β· chargeback detection Β· dunning failure detection Β· webhook observability Β· fastapi stripe webhooks


πŸ› οΈ More Dev Tools

Built by the same maker β€” if you're interested in algorithmic trading:

TradeSight β€” AI Paper Trading Strategy Lab β†’ β€” Python trading bot with overnight strategy tournaments, RSI confluence, and Alpaca integration.

License

MIT β€” see LICENSE


Built by an indie maker who got burned by a silent dunning failure. Stripe is great β€” but it doesn't tell you when things go wrong until it's too late.