← Playbook

I built a childcare compliance product in Go in six weeks. Then I stopped, on purpose.

ComplianceKit was a working product for licensed daycares in three states: rules engine, document chasing, mock inspections and its own PDF e-signature, in one Go binary. Here is why I built it, why Go, the timeline, and why the hard part turned out to be everything that is not code.

2026-10-15/8 min read/Levelbrook AI Practice

By Patrick Donahue.

The problem I could not stop thinking about

My children are one and three, so childcare is not an abstract market for me. When I started reading how licensed centres actually stay licensed, the thing that stayed with me was the binder. Every licensed centre has one, or several: immunisation certificates for each child, background checks and CPR cards for each teacher, fire drill logs, the posted notices, the staff-to-child ratio for every room. A state inspector can walk in unannounced and pull any of it. Each record expires on its own schedule, and most directors track the whole thing in paper and a spreadsheet, so a gap is usually discovered by the inspector.

Years ago in Berlin I worked in early childhood education, so I had some feel for how little spare attention the people running a centre have. The director is also the person covering a room when a teacher calls in sick. Nobody in that building is going to read a regulation on a Tuesday afternoon to work out which form a new hire’s tuberculosis test needs to be on.

That was the product: keep a centre ready for an inspection on any given day, not just the week before one. I called it ComplianceKit.

What it does

ComplianceKit models the licensing rules for California, Texas and Florida as deterministic code, with the regulation cited next to each rule (Florida’s F.A.C. 65C-22.006(4), the DH 680 immunisation form, and so on). It tracks children, staff, rooms and documents with their expiry dates, and scores a centre’s readiness from 0 to 100 with the top gaps and a fix for each. It chases the parents and staff who owe a document at 90, 60 and 30 days, then weekly, through upload links that need no account. It runs a mock inspection against the state’s real checklist (California LIC 9099, Texas Form 2936, Florida CF-FSP 5316), and it has an Inspector View, a read-only screen the director can hand to the inspector. Permission slips and consent forms are signed in the browser through a PDF e-signature pipeline I wrote rather than rented, with a SHA-256 audit trail on both sides.

38,000lines of Go in the backend
71Go test files
16-28 MiBresident memory in production
48.7 MBcontainer image

Why Go

I had spent seven years on a large multi-tenant product in a framework that hands you migrations, mailers, jobs and an admin screen on day one, and for that kind of product, with a big team and a big schema, that trade is right. ComplianceKit was a different animal. It was one person’s product that had to run cheaply for years and be correct about things that matter to parents. Go fitted that shape for four concrete reasons.

The rules engine had to be boring. A compliance result has to be explainable to a director and, if it ever came to it, to a regulator. In Go the rule packs are pure functions over a snapshot of facts: no I/O, no model call at evaluation time, the same input always gives the same output. That makes them table-testable, and Go’s table tests are about the least ceremonious way there is to write a few hundred cases of “a staff member hired on this date, in this state, with these documents, is compliant or is not”.

The sensitive parts are in the standard library. The e-signature flow needs SHA-256 hashing, HMAC-signed capability links, constant-time comparisons and careful handling of uploaded bytes. Go ships all of that in crypto/* and net/http, so the security-relevant surface is code I can read rather than a stack of third-party packages I have to trust.

One process does everything. The background work (document chasing, nightly readiness snapshots, session clean-up, trial reminders, retention purges) runs as one goroutine per chore, all listening to the same context, which is cancelled on SIGTERM. There is no queue, no cache server and no worker fleet to pay for or keep alive. A deploy is “build the image, swap the container”. A backup is “copy one SQLite file”.

It ships as one static file. With CGO_ENABLED=0 and the pure-Go SQLite driver, the binary has no shared libraries, so the runtime image is distroless and under 50 MB. On a small shared VM it sits at about 16 to 28 MiB of memory. For a product whose customers are small businesses, that is the difference between a margin and a hobby.

I went deeper on each of these, with the code, in a separate essay.

The timeline

ComplianceKit, April to October 2026. Dates and commit counts are from the repository history.
ComplianceKit, April to October 2026. Dates and commit counts are from the repository history.

The first commit landed on 16 April 2026 with the scaffold, the three state rule packs and the data model. By 20 April there was an end-to-end MVP and an audit pass with integration tests for the California, Texas and Florida launch. May was the heavy month, 104 commits: the document chasing (“Chase Mode”), the mock inspection and Inspector View, evidence photos with EXIF stripping, computed ratios per room, rate limiting, the e-signature pipeline, and a long run of fixes from testing it in a browser the way a director would. The last product commit was on 27 May.

Why I stopped

The short version is the one I give in conversation: building software has become dramatically cheaper, and selling it has not. ComplianceKit was ready well before I had a credible way to put it in front of the people who would buy it.

The longer version has three parts.

The buyer is the hardest person in the building to reach. A centre director is on the floor most of the day, does not sit in front of email, and is rightly sceptical of a stranger offering to handle children’s health records. The channels that work for that buyer are slow and personal: state associations, licensing consultants, conferences, the owner of a group of centres vouching for you. They reward someone who can show up in person for a year, and that was not a year I could fund.

Every state is a new product. The rules engine made adding a state clean in code, but the work is mostly outside the code: reading the administrative code, mapping each requirement to a document, and staying current when it changes. Three states was a reasonable launch. Thirty would have been a regulatory research business with some software attached.

The cost of being wrong is high. A compliance tool that says “ready” when a centre is not is worse than no tool. That is a responsibility I was happy to take on with paying customers and a feedback loop, and not one I wanted to take on with nobody using it.

So at the end of May I made the call to stop rather than drift. I archived the product, took the old subdomain down in June, and kept the code.

What I did next

In June I started Porchlight, which records the life stories of people living in senior care so that the care team (activity staff, aides, nurses, anyone new who walks into the room) and the family know who that person is. It has a similar buyer, a care facility, and I went into it with the ComplianceKit lesson front of mind: the distribution work started alongside the code instead of after it. Porchlight has had a GeekWire spotlight, a podcast interview and pilot conversations with facilities. It does not have paying customers yet, and I say that plainly because the honesty is the point of this essay.

Bringing ComplianceKit back as a demo

In October I brought ComplianceKit back up, because it is the most complete Go system I have written and I wanted people to be able to click through it rather than take my word for it. Running it from a clean checkout turned up real bugs, which I am glad I found myself:

  • Timestamps stored as TEXT in SQLite were scanned straight into time.Time. The pure-Go driver only converts columns declared as DATE, DATETIME or TIMESTAMP, so it compiled, passed the unit tests and returned a 500 on the dashboard at runtime. The same bug made every subscriber look inactive. I fixed it with small scanner adapters.
  • The e-signature store targeted tables that no migration created, and its routes were mounted under a doubled prefix. I added the migration, split the signer routes so they are authorised by token rather than login, and closed a cross-tenant overwrite on the field layout endpoint while I was in there.
  • The whole thing now runs as one container in a demo mode: embedded migrations on boot, local disk storage behind HMAC-signed URLs, email and SMS logged instead of sent, and one-click private sandboxes seeded with fictional data. Continuous integration is green on both the Go and the front-end suites.

You can try it at compliancekit.levelbrook.com with demo@example.com and inspection-ready, and the code, including an architecture document that ties every claim to a file, is at github.com/tachyurgy/compliancekit.

What I took from it

I would make the same technical choices again. Go gave me a system that one person could hold in their head, that runs on almost nothing, and that I could reopen five months later and debug in an evening. The rule packs, the capability links and the single-binary deploy all held up.

The decision I would change is the order. I would find the first ten directors who would pay before writing the e-signature pipeline, not after. Code is now the cheap part of a product, and the expensive part is earning the trust of the person who has to say yes.

The product is shelved. The engineering is the part I am proudest of, and it is all there to read.

Sources and things reacted to
  1. ComplianceKit (GitHub): Go backend, React frontend, self-hosted PDF e-signature 124 commits, April to October 2026; ARCHITECTURE.md covers the design file by file
  2. ComplianceKit live demo fictional data; sign in with demo@example.com / inspection-ready
  3. One binary, one SQLite file, a goroutine per chore the longer technical essay on the Go choices, read from the source
Keep reading

This is what we do all day.

Support automation, AI phone agents, n8n back-office work, and the engineering loop itself — always behind a gate you control.