Skip to content
TODD BROWN
« Writing

Seven systems, about 2,400 teams, six weeks, zero rollbacks

The go-live was 29 May 2026. Seven systems into one CRM, covering roughly 2,400 teams for a national amateur sports league. No rollbacks.

One piece of that engagement — the data mirror, a HubSpot integration into the league's own registration system — shipped with its audit findings left in the code, dated and severity-coded. Some were fixed. Eight stayed open. The code shows what was known to be unresolved.

What it was

The league ran registrations, payments, scheduling, compliance tracking, reporting and communications across seven separate systems. I rebuilt their revenue operations around a single HubSpot CRM, designed and configured from scratch during the same engagement. One deliverable inside that rebuild was a backend integration I wrote: a one-way data mirror that copies team-application lifecycle events out of the league's registration system (Python/Django + Celery) into the new CRM.

The registration system itself is owned and maintained by an outside development agency. They reviewed my integration code, merged it into their codebase, and own deployment. The mirror is live in production: I pulled a real HubSpot company record created by the integration, with all three lifecycle stages — initial submission, NDA signed, final approval — landing correctly over a two-day window, directly from HubSpot's own property-history interface.

Status word: live.

Additive-only, reversible by design

The integration was built to leave no trace if switched off. Four patch points were specified in the registration system's existing code — three required plus one conditional legacy route — each a small, additive change of 6 to 12 lines to an existing file: a serializer, an e-signature service, an insert path, and a model file. My estimate put the total lines added to existing client code, across all patch points and settings, at under 80.

I chose explicit hook calls at named locations over Django signals specifically so the change would not surprise the system's own maintainers, who had never used a signal in that codebase before.

The integration defaults to safe: a feature flag defaults to off, a separate dry-run flag defaults to on so the sync logs the payload it would send and exits before calling HubSpot. Every write is an idempotent upsert keyed on a stable external application ID. The sync is wrapped in a database transaction commit hook, so a rolled-back save never produces a HubSpot write. Log lines carry only an application ID and an event name — no personal data.

Turn the feature flag off and the system runs as if the integration was never there.

The audits, left in the code

The mirror's shipped code carries three numbered rounds of adversarial audit findings — AUDIT 001, 002, and 003 — left as permanent, dated comments in the source files. Each finding is severity-coded: critical, high, medium, low. At least 3 findings are explicitly marked resolved with a date. Eight remained open as of the last commit I read.

I did not fix or hide the open findings. They are dated in the code itself, so a reviewer can see what was already known to be unresolved.

A separate, dedicated field-coverage audit caught a data-integrity gap that no functional test had surfaced. A form field submitted by the client's front end as web_site did not match the name the receiving code expected: website. Because the field was optional, the mismatch was treated as simply absent rather than an error, and the value was never stored anywhere — not just never forwarded to HubSpot.

It was found two months after the initial merge, through the field-coverage audit rather than a bug report.

What broke and how I fixed it

The field-coverage audit was a dedicated pass on 10 July 2026, two months after the initial merge on 27 May, not a response to a bug report. Optional fields fail silently: a test suite that only exercises the happy path will not catch a front-end field name that does not match what the backend expects.

Eight audit findings were still open as of the last commit I read (4 August 2026). They stay in the code as dated, severity-coded comments. The code belongs to the league, not to me, so leaving them visible was a deliberate choice: whoever reads the code next can see what was already known to be wrong.

The numbers

  • Seven systems consolidated into one CRM (measured).
  • About 2,400 teams covered by the new system (approximate).
  • Six weeks from start to go-live, 29 May 2026 (measured).
  • Zero rollbacks (measured).
  • Under 80 lines added to the client's existing registration codebase, across all patch points and settings (estimated).
  • Three rounds of adversarial audit, findings left in the code (measured).
  • Eight audit findings remained open as of the last commit I read (measured).
  • One data-integrity gap caught by the field-coverage audit two months after the initial merge (measured).

What is next

Seven systems into one, roughly 2,400 teams, just six weeks, zero rollbacks. The open findings are tracked in the code itself, with a clear list and severity order for whoever picks them up.