Skip to main content

Self-hosted Stripe billing anomaly detector โ€” catch duplicate charges, fraud spikes, and silent lapses in real time.

Project description

๐Ÿ” 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

Detector What It Catches Severity
charge_failure_spike Failure rate > 15% over 1 hour โ€” gateway issue or card BIN attack ๐Ÿ”ด High
duplicate_charge Same customer charged twice within 5 min โ€” idempotency bug ๐Ÿšจ Critical
fraud_spike Dispute/chargeback rate exceeds threshold โ€” active fraud campaign ๐Ÿšจ Critical
negative_invoice Invoice total < 0 โ€” broken promo stacking or discount bug ๐ŸŸก Medium
revenue_drop MRR > 15% below 7-day rolling average โ€” silent churn or billing break ๐Ÿ”ด High
silent_lapse Active subscription with no successful payment in period ๐ŸŸก Medium
webhook_lag Events 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]?

BillingWatch Datadog Baremetrics Stripe Radar
Cost Free (self-hosted) 5+/mo 29+/mo Built-in (limited)
Your data leaves your server? โŒ Never โœ… Yes โœ… Yes โœ… Yes
Custom anomaly logic โœ… Full control Partial โŒ โŒ
Stripe-specific detectors โœ… 7 built-in โŒ General โŒ Metrics only โŒ Fraud only
Self-hostable โœ… Yes โŒ โŒ โŒ
Alert destinations Email + webhook Many Email Dashboard 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

Endpoint Method Description
/health GET Health check
/docs GET Interactive Swagger UI
/webhooks/stripe POST Stripe event ingestion
/webhooks/alerts GET Recent anomaly alerts
/webhooks/detectors GET Registered detectors list
/metrics GET total_events, events_by_type, uptime_seconds, detector_count
/metrics?window_hours=N GET Rolling window metrics (0.1โ€“168h)
/metrics/detectors GET Per-detector alert counts + severity
/metrics/recent-events GET Most 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


๐Ÿ”— Related Projects & Alternatives

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

Tool Type Cost Why BillingWatch Instead
Datadog Full observability $5+/mo General-purpose APM, no Stripe-specific detectors
Baremetrics SaaS analytics $29+/mo Analytics dashboards, not real-time anomaly alerts
Stripe Radar Fraud detection Built-in Card fraud only โ€” no dunning failures, duplicate charges, or webhook lag
Sentry Error monitoring $26+/mo Code errors, not billing events
ChartMogul Revenue analytics $100+/mo Historical charts, not real-time detection
Lago Open-source billing Self-hosted Full 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

billingwatch-1.0.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

billingwatch-1.0.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file billingwatch-1.0.0.tar.gz.

File metadata

  • Download URL: billingwatch-1.0.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for billingwatch-1.0.0.tar.gz
Algorithm Hash digest
SHA256 667870064a7ab3c48789af4902b580a70c30b5ccc566ef59e593d354ed71bc00
MD5 ef8caa3dd134d99e96bdf5792e5edc23
BLAKE2b-256 5c8e7075feededb9f593d59e4ca958936ce512b9dba92c17abeae0d87e6b626b

See more details on using hashes here.

File details

Details for the file billingwatch-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: billingwatch-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for billingwatch-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 43cb34575b5673d481df3e8a41c9f861fcbb26a6d7e681f21af2fa747da416cc
MD5 4f1e0aa0707189d4e3be0a23d7be18cb
BLAKE2b-256 72e1ad321662a95d44bae406f68ee607382da7a572569857af551a234303a1aa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page