All previews
Charging Software453 wordsnot yet seeded

OCPP Backend Development for Charging Platforms

What a charging backend has to do beyond accepting messages: connection state at scale, transaction integrity across interruptions, and tolerating chargers that behave differently.

Technically reviewed by Akhil Joy, CEO. Last reviewed 2026-09-01.

Building a charging backend is not primarily a protocol exercise. The protocol is documented and finite. The difficulty is holding accurate state for thousands of long-lived connections whose counterparties are unreliable and inconsistent.

Every hard problem in a charging platform is a variant of that.

Long-lived connections change the architecture

Chargers hold persistent connections for weeks. That is unlike request-response web traffic and it constrains how the platform can be deployed: a routine restart drops every connection, and a fleet reconnecting simultaneously arrives as a thunderherd.

Handling this needs connection state that survives process restarts, or a deployment model that drains connections gracefully rather than dropping them.

Transaction integrity across interruptions

A session may begin, the connection may drop, the charger may reboot, and the stop may arrive hours later or never. The platform must resolve every one of those into a defensible billing record.

That means transactions cannot be held in memory tied to a connection. They are durable state with a lifecycle independent of whether the charger is currently reachable.

Duplicates are guaranteed

A charger that does not receive an acknowledgement will resend. Sooner or later every message type arrives twice, and the backend must recognise it rather than treat it as new.

Idempotency is therefore a design requirement, not a refinement. Without it a network will double-bill drivers, which costs more in trust than the energy was worth.

Tolerate divergent charger behaviour

Chargers differ in configuration keys supported, error code mapping, status transitions, and how strictly they follow the specification. A backend written against one vendor's behaviour will break on the second.

The pattern that survives is a core that handles the specification and a per-vendor adaptation layer that normalises the differences, with the raw exchange retained so unexpected behaviour can be investigated rather than guessed at.

Retain the exchange

The single most valuable operational feature is the ability to read what was actually exchanged with a specific charger at a specific time. It settles vendor disputes, diagnoses intermittent faults and answers billing questions.

Platforms that store only outcomes make every incident a matter of opinion. Storage costs money; not having the trace costs more.

Supporting two protocol versions is permanent

Fleets do not migrate atomically, so a backend serving any real network supports more than one version indefinitely. Treating that as a transitional state produces an architecture that fights the reality.

The versions differ enough in device and transaction model that this is close to supporting two protocols, and planning for it from the start is far cheaper than retrofitting.

Time is harder than it looks

Chargers drift, report in their own timezone handling, and deliver backdated transactions after outages. Tariffs are time dependent, so timestamp handling is a billing correctness problem rather than a formatting one.

Storing everything in a single absolute reference, and keeping the charger's reported time alongside the received time, is what makes later reconciliation possible.