← All writing
articleMay 19, 202518 min read

EV Charging Platforms: The Meter Is the Product and the Connector Is the Weakness

OCPP, the five-system transaction, demand charges on connected capacity, idle bays, and why public charging reliability is a hardware problem wearing a software costume.

IoTOCPPReal-TimeArchitecture
EV Charging Platforms: The Meter Is the Product and the Connector Is the Weakness cover illustration

Public EV charging looks like a solved problem until you try to make one reliable.

A charge point is a networked industrial device with a door, a screen, a card reader, a cable, and a connector that a member of the public yanks out of a vehicle forty times a day. It sits outdoors. It is bolted to concrete. Its metering has to be defensible in a billing dispute. And its customer is standing in the rain expecting it to work on the first try.

The software is not the hard part. The connector, the meter, and the electricity contract are.

The network, for scale

A network operator with 50,000 charge points and 60,000 connectors, since sites have more than one.

8,000  DC fast chargers   at 150 kW
42,000 AC chargers       at 7 to 22 kW
                        -----------
50,000 charge points, 60,000 connectors

sessions per day:
  8,000 DC x 6 sessions             = 48,000
  42,000 AC x 1.5 sessions          = 63,000
                                     --------
                                     ~111,000 sessions/day
peak: ~15% of sessions in one hour
      16,650 / 3,600 sec            = ~4.6 sessions/sec

Energy moved, and revenue:

48,000 DC sessions x ~45 kWh        = 2.16 GWh
63,000 AC sessions x ~12 kWh        = 756 MWh
                                     --------
                                     ~2.9 GWh/day
at ~$0.35 per kWh                   = ~$1.0 million/day gross

Then the number that decides whether the business works.

connected capacity:
  8,000 x 150 kW                   = 1.2 GW
  42,000 x 22 kW                   = 924 MW
                                     -------
                                     ~2.1 GW connected

average draw: 2.9 GWh / 24h         = ~121 MW
utilisation of connected capacity  = ~5.8%

A network that has paid for two gigawatts of interconnection and is using about a hundred and twenty megawatts of it, on average, is a network whose economics are set by fixed charges rather than by energy margin.

The charge point connects outward

The first thing to internalise about OCPP is that it is not like a web API.

most IoT:      platform -> device
OCPP:          charge point -> platform      (persistent outbound connection)

The charge point dials the central management system, authenticates, and holds the connection open. It is the same shape as a phone, a bank ATM, or a payment terminal.

This inversion determines almost everything about the platform’s behaviour.

The device needs a public address or a tunnel. A charge point on a private network with an inbound-blocked firewall cannot be reached, so it either has a routable address, an outbound-only VPN, or a brokered tunnel. For a hardware manufacturer shipping in volume, an outbound TLS connection to a known host is by far the simplest thing to implement and to certify.

The central system must tolerate fifty thousand inbound persistent connections. Not fifty thousand a second. Fifty thousand, at once, indefinitely, each with a heartbeat and a reconnect policy. That is a connection management problem of the same family as the vehicle platform, and the reconnection storm is the same storm.

The charge point’s clock and the backend’s clock must agree. Transactions have start and stop times, and a device that has been offline for an hour has an ambiguous transaction window that has to be reconciled.

A device that is offline is invisible. No connection, no status, and the platform has to distinguish “broken” from “network problem at that address” from “the site lost power”, because those need three different dispatches.

The protocol, in the terms that matter

OCPP has two versions in wide use: 1.6 over SOAP, and 2.0.1 over JSON and WebSocket. The vocabulary is small and the concepts are worth stating precisely, because the transaction model is the core of the product.

Charge point and connector. A charge point is the physical unit; connectors are the individual outputs. A site with four connectors is one charge point with four connectors, and each connector is independently available, charging, or faulted.

Authorization. Before a session starts, the driver identifies: a mobile app, an RFID card, or a credit card. The central system decides, and the charge point enforces.

Transaction. The billing period. It has a start, a stop, a meter start, a meter stop, and a set of meter values in between. This is the unit of money.

Meter values. Energy and power sampled over the session, sent while charging so the platform has a live view, and reconciled against the start and stop values at the end.

Status notification. The charge point’s state machine, reported on change: Available, Preparing, Charging, SuspendedEVSE, SuspendedEV, Finishing, Reserved, Unavailable, Faulted.

Remote start and stop. The central system can begin and end a session, which is what makes fleet and reservation charging possible.

Charging profile. A limit on power, sent to the charge point. This is the mechanism for site load management and it is the most under-used feature in the protocol.

Two features deserve particular attention because they decide whether the network is resilient or fragile.

Local authorization lists. A charge point can hold a list of authorised identifiers and start a session when the central system is unreachable. Without it, a backend outage means every charger in the country rejects every driver. With it, a small whitelisted subset of sessions can proceed through a network outage. This is one of the highest-value reliability features in the protocol and it is frequently left off.

Idempotency. OCPP 2.0.1 has explicit request identity, which matters because a charge point on a flaky connection will retry, and a retried StartTransaction that is not idempotent produces two transactions for one session.

The meter is the product

A charger produces energy that a member of the public is billed for, and the number comes off a physical device in the field. That makes metering a product and legal concern rather than a telemetry detail.

The questions that have to be answered:

  • Who owns the meter? Frequently the utility, sometimes the site host, sometimes the equipment manufacturer. It determines who calibrates it, who replaces it, and who a dispute is raised with.
  • How is it calibrated, and how often? A revenue meter that drifts is a financial and regulatory problem, and the calibration interval is dictated by rules that are not yours.
  • What is the tolerance on a session? A driver who disputes 2 kWh on a 45 kWh session is usually right, and a platform that rounds in its own favour will generate support contacts forever.
  • What happens if the device is reset mid-session? A power cut or a firmware update must not lose a transaction. The meter stop has to be recoverable from the device, which is a hardware requirement.
  • What is the dispute process, and how long does it take? A dispute that takes three weeks to answer is a chargeback, and a platform with a high dispute rate has a metering problem, not a customer service problem.

The reconciliation chain to preserve is: what the platform recorded, what the device recorded, and what the utility recorded. Any mismatch is a support case, and being able to show all three is what turns a dispute into a five-minute resolution.

The connector is the weakness

Not the electronics. Not the network. The physical bits that a member of the public handles.

Public DC charging involves a connector and latch assembly that will see thousands of insertions, often with a cable at an awkward angle, frequently in the dark. The observed failure distribution is roughly:

connector and latch assembly   the most common hardware failure
cable and strain relief        close behind, especially on DC
screen, card reader            common, and usually repairable in place
power electronics              rare, and the reason for a site visit

A DC connector assembly is also expensive and often replaced as a unit, which is why field service logistics and spare parts inventory are a real cost centre.

The consequence for software is that the platform has to model degraded states honestly rather than binary ones. A charger that cannot deliver power but can still take a payment is the most damaging failure mode available, because the failure is discovered after the money moves.

Available
Preparing
Charging
SuspendedEVSE      vehicle asked to pause
SuspendedEV        vehicle paused
Finishing
Reserved
Unavailable       administratively off
Faulted

And the deeper point about availability: a charge point that is online and broken is worse than one that reports offline. Offline is honest, dispatchable, and excluded from search. Online and broken is a driver standing in the rain with a working app.

So fault detection has to be active rather than passive. A charge point that reports Available and then fails to open its connector has not failed visibly, and the platform’s ability to notice that from telemetry alone is limited. The mechanisms that do work are a heartbeat that stops, a status change that does not make sense, a fault code, and a customer report.

Idle bays and the idle fee

An AC charger with a car that finished charging at 04:00 and is not collected until 09:00 is unavailable for five hours. Across a network, idle time is the largest single capacity loss in the business.

42,000 AC connectors
if 25% of time is blocked by a finished session
that is 10,500 connectors idle

The industry answer is a session fee charged after a grace period, sometimes escalating. It works, and it is unpopular, and it has to be disclosed clearly enough that a driver is not surprised by a line item they did not understand.

The alternatives that operators combine with it:

Notifications to the driver’s app when the session completes, with escalating reminders. Cheap and effective for drivers who want the reminder.

Blocking the bay reservation after a threshold, so the connector is shown as occupied and the app stops advertising it. This is the honest fix, because it makes the constraint visible to the next driver even if the first one has not moved.

Reservation-based charging for fleets and for sites with predictable patterns, which removes idle time by making the bay belong to a specific vehicle in a specific window.

Physical design. Bollards, bay markings, and cable management that make a bay hard to block. Unglamorous and effective, and it is a site-hosting decision rather than a software one.

Authorisation has three failure modes

Starting a session requires identifying the driver, and the three methods fail in completely different ways.

Mobile app. The best experience, the most capable, and the one that fails when there is no signal, no app session, or an out-of-date app. It also requires a pre-authorisation hold on the card, which means a card hold for every session, which is a payment cost.

RFID card. Works with no connectivity, which makes it excellent for fleet and unbanked users and poor for consumer acquisition. The card has to be provisioned, and provisioning is a real onboarding product with real failure modes.

Credit card, tap to pay. No app, no account, and exactly what an occasional driver wants. It puts a payment terminal and a PCI scope on a device in the rain, and it is where a large share of failed sessions come from when the reader is broken or the network is down.

The operational requirement is that a failure in any of the three has to produce a clean, specific error rather than a charge point that sits in Preparing forever. A charge point stuck in Preparing with a driver waiting is the single most common complaint in the industry, and it is a state machine bug rather than a hardware one.

A session is a five-system transaction

Here is what a single charging session actually involves.

1. driver        app or card identifies
2. app           POST /sessions
3. backend       authorise a card hold
4. backend       send RemoteStart to the charge point
5. charge point  authorise (centrally or from a local list)
6. charge point  start metering, report StartTransaction
7. charge point  report MeterValues while charging
8. driver        plug in, session runs
9. charge point  stop metering, report StopTransaction
10. backend      read the final meter stop
11. backend      reconcile meter values against the hold
12. backend      capture the card
13. backend      compute the bill: energy, time-of-use rate, session fee
14. utility      meter the site, for the demand and revenue calculation

Five independent systems: the driver’s device, the charge point, the OCPP backend, the payment processor, and the utility. Each has its own failure mode, its own latency, and its own idea of when the transaction ended.

The failure that dominates is the partial session:

  • the charge point stopped but StopTransaction never arrived, because the network dropped;
  • StopTransaction arrived but the backend crashed before capturing;
  • the capture succeeded and the app never learned about it, so the driver starts another session and pays twice;
  • the charge point thinks it authorised the session and the backend thinks the driver never did.

The design principles that handle these are the ordinary ones, restated for a device that is offline half the time:

  • Idempotent transaction identifiers, generated at the charge point, so a retried StartTransaction or StopTransaction does not create a second transaction.
  • Reconciliation, not notification. The charge point’s own view of a transaction is authoritative for the hardware, and the backend’s for money. A nightly or continuous reconciliation finds the cases where they disagree rather than hoping the messages all arrived.
  • Explicit unknown states. A session whose outcome is not yet known is a distinct state, and the billing system has to be able to hold it. Defaulting unknown to success over-bills and defaulting to failure under-bills and annoys everyone.
  • Unmatched sessions are a first-class queue. Driver has no session, backend has a transaction. That queue is where the reconciliation work lives, and it needs an owner.

Demand charges, which is where the money is

Electricity pricing for a large load is not a per-kWh rate. It is a per-kWh rate plus fixed charges, and the fixed charges are set by peak demand rather than by energy sold.

The structure, which varies by utility:

energy charge        per kWh delivered
demand charge        per kW of peak, typically the highest 15-minute
                     average in the billing period
contracted capacity  per kW of reserved capacity, some utilities
power factor         penalties below a threshold

The point that matters: a demand charge is incurred whether or not the energy is sold. A site that is connected for 1.2 megawatts and draws nothing still costs what the demand charge says, and a site that draws its full capacity for one quarter of an hour in a month pays for that quarter of an hour all month.

Which makes load management the highest-leverage operational feature on the site, and OCPP has had the mechanism for it in ChargingProfile for years.

The arithmetic on one site:

4 DC chargers x 150 kW          = 600 kW possible draw
demand charge at ~$15/kW/month

unmanaged, all four charge together     -> 600 kW peak -> $9,000/month
managed, site capped at 200 kW          -> 200 kW peak -> $3,000/month
                                       saving          $6,000/month

Six thousand dollars a month per site. Across a few thousand multi-charger sites that is tens of millions a year, for a piece of software that schedules power.

The engineering is not trivial, because capping a site means deciding who waits:

1. the site controller knows the site's hard power limit
2. each session requests a charging profile limit
3. the controller allocates headroom to active sessions
4. when a session ends, headroom goes to the next
5. fairness policy decides the order: first come, or shortest remaining time?

Two details that decide whether it works. The limit has to be enforced at the charge point, not at the backend, because a backend cannot cap a session when it is not reachable. And the driver has to be told they are being limited, because a car charging at 40 kW instead of 150 kW with no explanation reads as a broken charger.

Failure stories worth testing

Take the backend down for an hour

Every charger with a local authorization list keeps working for its listed identifiers. Every charger without one rejects every driver. Test the second case deliberately, because it is what a real outage looks like.

Drop the network mid-session

The charge point meters through the outage. On reconnect it reports the transaction. Confirm the final meter stop is the device’s, not an estimate, and that the session is reconciled rather than lost.

Force a power cut during a session

Confirm the transaction is recoverable from the device afterwards. If it is not, the revenue is unrecoverable and the hardware is wrong.

Reset a charge point with a session running

Same question. A reset must not lose a session’s energy.

Run four DC chargers simultaneously on a capped site

Confirm the cap holds, the power sharing is within the vehicle’s tolerance, and the drivers are told why they are slow.

Break a latch on a working charge point

It reports Available and cannot deliver. Confirm the failure is detected or reported quickly, because this is the failure the industry knows least about.

Have a card declined at the terminal

The charge point must leave Preparing cleanly, and the session must not become a charge on someone’s card after the fact.

Let two sessions start from one tap

Confirm the idempotency holds and the driver is not billed twice.

Disagree with the utility’s site meter

Confirm the three-way reconciliation is available: platform, device, utility. This is the query that resolves a disputed bill.

Reset a site’s supply during a demand-charge peak

Confirm the site controller respects the limit even when every session is active, and that sessions are shed in a defined order rather than all at once.

A production-ready architecture

  [ charge points ]  outbound OCPP 2.0.1 over TLS
        |  persistent connection, 50,000 of them
        v
  +--------------------------+
  | OCPP gateway             |
  |  connection management   |
  |  local auth list cache   |
  |  transaction identifiers |
  +------------+-------------+
               |  normalised events
               v
  +--------------------------+     +-----------------------+
  | Transaction service      |     | Site power controller |
  |  start, stop, meter      |     |  hard limit, fairness |
  |  reconciliation         |     |  profile allocation   |
  +------------+-------------+     +-----------+-----------+
               |                              |
     +---------+--------+                     v
     |                  |            +--------------------+
     |                  |            | Charge point       |
     |                  |            |  enforces the cap  |
     |                  |            |  at the device     |
     v                  v            +--------------------+
+---------------+  +------------+
| Metering store|  | Payment    |  hold, capture, void, dispute
| device + site |  +------------+
+---------------+
               |
        +------v------+
        | Utility     |  site meter, demand charges, tariff
        +-------------+

A sensible delivery checklist:

  1. Design for the charge point connecting outward, and plan the reconnection storm before the hardware ships.
  2. Turn on local authorization lists, because a backend outage should not reject every driver.
  3. Use transaction identifiers generated at the device, and make every transaction message idempotent.
  4. Maintain the three-way reconciliation: platform, device, and utility meter.
  5. Treat metering calibration, ownership, and tolerance as product requirements with owners.
  6. Make an unknown session outcome a distinct state, and have a queue for sessions that do not match anything.
  7. Implement site load management with the cap enforced at the charge point, and tell the driver.
  8. Charge a session fee after a grace period, and block the bay in the app so the constraint is visible to the next driver.
  9. Model the connector and latch as the expected failure, and stock parts for it.
  10. Detect unavailability actively, because a charge point reporting Available that cannot deliver is the worst failure available.
  11. Price the whole tariff, not just the energy rate, and put demand charges into the site economics.
  12. Give every failure mode above an owner and a runbook, because a field device will use all of them.

Common mistakes

Mistake What actually happens Better decision
No local authorization list A backend outage rejects every driver in the country Cache an allowlist on the charge point
Retried transaction messages create duplicates One session becomes two billable transactions Device-generated idempotent transaction ids
No reconciliation queue Sessions silently exist on one side of the system only Continuous reconciliation, with an unmatched queue
Defaulting an unknown session to success Drivers are over-billed and the dispute rate climbs Hold unknown as a state, resolve it explicitly
Load management enforced in the backend The cap fails exactly when the network is down Enforce at the charge point via charging profiles
No driver-visible power limit A capped car reads as a broken charger Tell them, and show the expected time
Pricing only the energy rate Demand charges make the site economics unviable Model the full tariff including peak demand
Online and broken is treated as available Drivers arrive at a charger that cannot deliver Active fault detection, honest status
Binary availability A charger that cannot open its connector shows as fine Model the full status set and connector health
Ignoring idle time A quarter of the network is blocked by finished sessions Session fees, notifications, bay blocking
No session fee disclosure The line item is a surprise and the dispute rate rises Clear disclosure and a visible grace period
One authorisation method treated as the only one A single failure mode covers the whole network App, RFID, and tap-to-pay, each with its own error path
Sessions stuck in Preparing The most common complaint in the industry Timeouts that leave the state cleanly
The meter is an afterthought Disputes cannot be resolved and revenue is arguable Own the calibration, tolerance, and dispute process
Field parts not modelled A latch failure becomes a multi-day outage Spare inventory and a dispatch decision tree
Peak demand unshaped One fifteen-minute spike sets the month’s bill Site power capping with a fairness policy

The complete story in one minute

A charge point initiates a persistent outbound OCPP connection to the platform, and fifty thousand of those connections are the availability problem rather than the throughput one. Each charge point holds a local authorization list so a backend outage does not reject every driver, and each generates its own transaction identifiers so a retry on a flaky connection does not produce two billable sessions.

A session crosses five systems: the driver’s app or card, the charge point, the platform, the payment processor, and the utility. The platform’s job is to keep an explicit state for a session whose outcome is not yet known, to reconcile the device’s view against its own continuously, and to have a queue for sessions that match nothing, because that queue is where the reconciliation work actually lives.

Revenue comes from a physical meter in the field, so calibration, ownership, tolerance, and the dispute process are product requirements with named owners, and the three-way reconciliation between platform, device, and utility is what turns a disputed bill into a five-minute answer.

The biggest lever on site economics is not price. It is demand charges, which are billed on peak or contracted capacity rather than on energy sold, so a site with four 150 kW chargers can pay for 600 kW of peak because four cars plugged in at once. Capping the site at 200 kW and allocating headroom fairly saves real money, and the cap has to be enforced at the charge point, because a backend that cannot be reached cannot enforce anything.

And the physical reality is that the connector, the latch, and the cable fail far more often than the electronics, so status has to be modelled in enough detail to tell the difference between a charger that is available and one that is merely powered on.

That is the whole path:

identify -> authorise -> start metering -> session -> stop -> reconcile -> capture
                |
                +-> capped by a site controller, enforced at the device

The hard parts were never the protocol. They were a device that connects outward and is offline half the time, a revenue number produced by hardware in a field, and the discovery that the electricity contract, not the software, determines whether the network makes money.

What this team still owns

OCPP interoperability is a starting point, not proof that a session will reconcile. The operator owns the mapping among charge point, EVSE, connector, authorisation token, transaction event, meter values, tariff, and payment. Store device sequence/timestamps alongside receipt time, keep an unmatched-session queue, and test recovery after reset, reconnect, duplicated transaction events, and an unavailable central system. Smart-charging limits needed for electrical safety must still be enforceable locally.

Technical references

Keep reading
Browse everything