Dallas Crilley
← All case studies

Billing automation · Shipped · Requirements from operators through production

Meter

Intermedia usage, billed straight into ConnectWise.

Billing automation that moves telecom usage into customer invoices, replacing manual reconciliation.

Who it helps: The MSP running Meter uses it to make Intermedia-to-ConnectWise billing practical. Without it, an operator re-keyed line items account by account.

At a glance

language
Python 3.11 (FastAPI), React 18 (TypeScript)
sync engine
27 modules, idempotent ConnectWise sync
ingest
Selenium (Intermedia exposes no billing API)
deploy
Fly.io, 2-process (app + scheduler)
ownership
Requirements from operators through production
in production
An MSP billing cycle; longest-running system in the portfolio
repo
Private production repo; walkthrough available on a screen share

The problem

I built Meter for an MSP that was re-keying Intermedia line items into ConnectWise during each billing cycle. Charges could be misassigned and retries could create duplicates, so I made the cycle idempotent and added reconciliation against real customer billing.

How it’s built

  1. Idempotency for a system with no safe retry

    I designed DB-level per-account locks to stop concurrent syncs from double-billing. When ConnectWise returns an ambiguous 5xx, I query back within a 15-minute window and match a content hash to confirm whether the charge posted. The operator gets a confirmed outcome instead of a duplicate charge or a silent failure.

  2. Edge cases turned into code

    ConnectWise rejects additions dated before an agreement billing start. An effective-date handler detects that exact error, fetches the start date, adjusts, and retries, removing a class of manual corrections.

  3. Preview-before-sync and reconciliation audits

    Operators can diff what the system would send against what ConnectWise already holds, with comparison keys that normalize display-string drift so it does not surface as a false mismatch. The reconciliation audit exposed a tax-row identity bug across affected accounts.

By the numbers

a real MSP billing system
In production
modules in the sync engine
27
Alembic schema migrations
35
accounts covered by one reconciliation audit (self-reported)
202

How to read these numbers

Figures marked self-reported are stated in docs or commit history that I could not reproduce from the repository alone. Every other figure is traced to code or clearly marked self-reported.

  • 202: Basis: December 2025 incident snapshot: 931 audited work items and 634 mismatching billing cycles. It describes audit blast radius, not steady-state volume.

Where this stands today

I maintain Meter in production as the portfolio’s longest-running system. A December 2025 reconciliation audit caught a tax-row identity bug. Its figures and basis are above.

The production repo stays private. I can walk you through the sync engine, scheduler, reconciliation path, and tests on a screen share. The public architecture post covers the retry decision.

Read the architecture post

Get in touch

Want the parts of Meter that are not in a public repo? Email me at dallas@dallascrilley.com.