Metering platform for a regional energy retailer
The retailer inherited three meter vendors with three protocols, and a billing team reconciling exports by hand every month.
The situation
Three acquisitions in five years left the retailer with three meter estates, three vendor portals and three export formats. The billing team downloaded CSVs from each, reconciled them in a spreadsheet, and manually chased the gaps.
What made it hard
Metering load is not evenly distributed. Every meter reports on the quarter hour, so the platform is idle for fourteen minutes and then receives everything at once. The inherited system was sized for the average and lost readings on every spike.
Worse, nobody could say how many were lost. There was no dead-letter path, so a malformed payload from one vendor's firmware simply vanished, and the gap was discovered by a customer complaint weeks later.
How we built it
One schema, translated at the edge
Rather than teach every downstream system three formats, translation happens once at the gateway. Each vendor's payload is mapped into a single versioned schema, and everything above that layer only ever sees one shape. Adding a fourth vendor is now a translator, not a project.
Absorbing the quarter-hour spike
EMQX accepts the burst, Kafka absorbs it, and consumers drain at their own pace into TimescaleDB. Peak throughput measured at 9,000 messages a second against a launch requirement of 2,000, so growth does not need a re-architecture.
Making loss visible
Every rejected payload lands in a dead-letter topic with the validation error attached. The console shows the dead-letter rate as a first-class metric, which surfaced a firmware bug in one vendor's estate during the pilot that had been silently dropping readings for over a year.
One console for two audiences
Field engineers commission meters from the same application the operations team monitors, so a newly commissioned meter appears in the fleet view immediately rather than after an overnight sync.
What changed
Billing moved from three manual exports to one API call, saving roughly four days of work per cycle. The dead-letter path paid for itself in the pilot by exposing a fault that had been quietly corrupting a subset of readings.
What we would tell the next team
- The peak matters, not the average. Asking for peak message rate in discovery changed the entire architecture.
- The dead-letter path was scoped as a nice-to-have and turned out to be the most valuable single feature.
- Commissioning is part of the product. Treating it as an afterthought is how estates end up with untracked meters.
Results above were measured by the client against their own baseline. We are happy to arrange a reference call where the contract allows it.
Other builds worth reading
Cold-chain monitoring for a cross-border distributor
Vaccine shipments were being written off because temperature breaches were only discovered on arrival. Paper loggers gave no way to intervene while a truck was still moving.
Predictive maintenance across two CNC plants
Spindle failures stopped lines without warning, and the maintenance window was booked around a calendar rather than the state of the machine.
Tell us what you are trying to measure
An engineer reads every message and replies within one working day. The first call is a conversation about your problem, not a sales script.