Why migrate now?
Migrate when your roadmap needs richer device management, stronger security, or grid-aware smart charging — not just because a newer version exists. OCPP 1.6 still runs reliable fleets, but it caps what you can build on top of it.
OCPP 1.6 was designed when most stations had a single connector and firmware updates were rare. Multi-connector hardware, dynamic load management, ISO 15118 Plug & Charge, and layered tariff structures all push past what its flat message set was meant to carry. You can bolt on workarounds, but each one becomes backend logic you maintain forever.
OCPP 2.0.1 isn't a version bump. It rearchitects how charge points and central systems describe themselves, report transactions, and negotiate security. That deeper model is the reason migration takes planning: most of the work is mapping old assumptions onto the new structure, not flipping a switch. Treat the trigger as a capability gap you can name, then scope the rollout around it rather than around the calendar.
Key differences between OCPP 1.6 and 2.0.1
The biggest differences sit in four areas: the device model, security, smart charging, and how transactions are reported. Each one changes assumptions baked into 1.6 backends, which is why a migration is structural rather than cosmetic.
Message structure
OCPP 1.6 uses a flat message format. Every operation has a request and a response, and the data model is implicit. To know the real state of a connector, you stitch it together from StatusNotification messages and remember what each charger told you last. That implicit state is where mixed-fleet bugs hide.
The OCPP 2.0.1 specification introduces a component-variable model. Every configurable aspect of a charger is a component (ChargingStation, EVSE, Connector) holding typed variables (Available, Power, and so on). State becomes explicit and queryable: you ask the charger what it is and how it is configured instead of inferring it. The practical payoff is diagnostics. When a station misbehaves, you can read its component tree rather than replay a log of notifications and guess at the gaps.
Security profiles
OCPP 1.6 has no built-in security model. Most deployments land on Basic Auth over WSS at best, and plain WS at worst, which means a charger's identity rests on a shared secret in a config file. OCPP 2.0.1 formalizes security into three named profiles so you can state, audit, and enforce a posture instead of improvising one.
The three profiles are:
- Profile 1: Basic authentication over TLS
- Profile 2: TLS with client-side certificates (mutual TLS)
- Profile 3: Profile 2 plus signed firmware updates
If you handle payment data or run public chargers, Profile 2 is the minimum to target. The hard part is rarely the protocol — it is the certificate lifecycle. You need issuance, rotation, and revocation across thousands of field devices, and that operational machinery has to exist before you flip stations onto mutual TLS. Plan it as its own workstream inside the migration.
Smart charging
OCPP 1.6 supports basic charging profiles via SetChargingProfile. It works for static schedules and simple load caps, but it cannot express cost signals or react to external grid constraints. OCPP 2.0.1 extends the same profile concept into a model that can optimize against price and capacity in near real time.
OCPP 2.0.1 adds:
- Cost-based charging — the central system communicates energy prices so the charger shifts load to cheaper windows
- External constraints — grid or site operators can signal capacity limits the charger must respect
- Priority charging — different profiles coexist for different use cases on one station
For most operators this is the feature that justifies the move. If you are doing depot charging, demand-charge avoidance, or dynamic site load management, 1.6 forces that logic entirely into your backend. 2.0.1 lets the charger participate, which keeps optimization closer to the asset and more resilient when the backend connection drops.
Transaction handling
In OCPP 1.6, a transaction is implicitly tied to a connector via StartTransaction and StopTransaction. If the connection drops mid-session, you reconstruct what happened from buffered MeterValues and hope the start and stop pair up cleanly. Billing disputes often trace back to exactly this gap.
OCPP 2.0.1 introduces explicit transaction events (TransactionEvent with Started, Updated, and Ended triggers). Every meaningful state change carries its own event, with a stable transaction id and sequence numbers, so the backend can detect missing events and rebuild a session deterministically. This matters most where OCPP feeds OCPI for roaming settlement: a clean transaction record on the charging side becomes a defensible Charge Detail Record downstream. See how the two protocols connect in our OCPI overview.
Which migration strategy should you choose?
Choose dual-stack for most production fleets, rolling firmware upgrades for small homogeneous fleets, and big-bang only for greenfield or decommissioning. The right answer follows fleet size, vendor firmware readiness, and how much downtime your sites can absorb.
Strategy 1: Dual-stack gateway
Run OCPP 1.6 and 2.0.1 endpoints in parallel. New chargers connect via 2.0.1, existing chargers stay on 1.6, and a translation layer normalizes both into one internal model your application logic consumes. This decouples the firmware timeline from the backend timeline, which is what makes long coexistence survivable. The cost is the gateway itself: you own a translation layer that has to stay faithful to both protocols as edge cases surface in the field.
Strategy 2: Rolling firmware upgrades
If your charger vendor ships stable 2.0.1 firmware, upgrade station by station behind scheduled maintenance windows. This fits small, homogeneous fleets where one or two vendors cover everything and you can validate each batch before moving on. It gets fragile fast with mixed hardware, because every vendor's 2.0.1 implementation drifts and you end up debugging firmware instead of architecture.
Strategy 3: Big-bang cutover
Replace the backend in one coordinated switch. This is only sane for greenfield deployments or when the legacy system is being retired anyway. For an operating fleet it concentrates all risk into a single window with no graceful fallback, so the blast radius of any wrong assumption is the entire network at once.
Migration strategy decision matrix
| Criterion | Dual-stack gateway | Rolling firmware upgrade | Big-bang cutover |
|---|---|---|---|
| Best fit | Mixed production fleets | Small, single-vendor fleets | Greenfield or decommissioning |
| Coexistence period | Long, by design | Medium, shrinking per batch | None |
| Downtime risk | Low | Low per site | High, network-wide |
| Rollback ease | High, reroute traffic | Medium, reflash firmware | Low, no fallback |
| Main cost | Maintain translation layer | Vendor firmware variance | Concentrated cutover risk |
| Vendor dependency | Low | High | Medium |
A realistic migration timeline
A safe migration moves through five phases: assess, pilot, coexistence, scaled rollout, and decommission. Each phase has an explicit entry gate, so you advance on evidence rather than on schedule pressure. Treat the phase boundaries as decisions, not milestones.
Phase by phase
- Assess. Inventory firmware versions, vendors, and security posture. Name the capability gap driving the migration and confirm which vendors actually ship production-grade 2.0.1. The CPO migration checklist is built for this step.
- Pilot. Migrate a small, representative slice covering each vendor and hardware type you run. Validate against real sessions and real billing output, not just the OCTT.
- Coexistence. Run 1.6 and 2.0.1 side by side under your normalized internal model. In mixed-fleet rollouts the failure usually shows up here, as state drift between protocols, so watch transaction integrity and connector status closely.
- Scaled rollout. Expand in batches grouped by vendor and site, validating each batch before the next.
- Decommission. Retire 1.6 endpoints only once no production traffic depends on them.
Rollback and coexistence criteria
Define rollback rules before the pilot, not during an incident. A batch should roll back when transaction integrity, connector status accuracy, or security handshakes regress against your 1.6 baseline. With a dual-stack gateway, rollback is rerouting a station to its 1.6 endpoint, not reflashing firmware under pressure. Set an explicit coexistence exit gate too: 1.6 retires only when zero production sessions, billing flows, or roaming records still depend on it. The rollout blueprint frames these pilot, coexistence, and full-rollout gates in practice.
What are the most common migration pitfalls?
Most failures trace to four assumptions: that messages map one to one, that compliance-tool behavior equals field behavior, that mixed fleets are temporary, and that security can wait. Each one is avoidable with explicit planning up front.
Don't assume 1:1 message mapping. Many OCPP 1.6 messages have no direct 2.0.1 equivalent. StatusNotification splits into connector status plus the component-variable model for charger state, so a naive translation loses information.
Test with real hardware. Firmware implementations of OCPP 2.0.1 vary widely between vendors. What passes the OCTT (OCPP Compliance Testing Tool) can still behave differently on production hardware, especially around transaction events and certificate handling.
Plan for mixed fleets. You will likely run 1.6 and 2.0.1 chargers together for years. Your backend has to treat that as the steady state, not a temporary phase, which is exactly what a normalized internal model buys you.
Don't skip security. If you are already migrating, implement at least Security Profile 2 now. Retrofitting certificate-based auth across a deployed fleet later is harder, and riskier, than building it in during the move.
How does a normalized internal model reduce migration risk?
A normalized internal model is the single highest-leverage decision in an OCPP migration. The idea is simple: terminate both 1.6 and 2.0.1 at a translation layer, then express everything above it in one protocol-agnostic representation. Your billing, monitoring, and smart-charging logic then never branches on protocol version.
This is what makes coexistence sustainable rather than a tax. Without normalization, every feature you build has to handle two transaction models, two device models, and two security stories, and that conditional logic spreads through the whole backend. With it, the version difference is contained at the edge. A charger upgrading from 1.6 to 2.0.1 changes how it speaks to the gateway and nothing about how your application reasons about it.
The trade-off is honest: you own that translation layer, and it has to stay faithful as field edge cases appear. But that cost is bounded and central, where two-protocol conditional logic scattered across services is neither. For most operators, normalization is what turns a multi-year mixed fleet from a liability into a non-event. Our ultimate guide to OCPP covers the protocol foundations, and the EV charging software RFP template helps you test vendors on exactly this capability.
Frequently asked questions
Is OCPP 2.0.1 worth it if our fleet still runs on 1.6?
Usually yes for medium and large fleets, especially where security, grid-aware smart charging, or richer device management matter. If your roadmap has no concrete need for those capabilities, staying on 1.6 a while longer is defensible. Migrate against a named gap, not against the version number alone.
Can we migrate charger by charger?
Yes, and it is one of the most practical approaches when your vendors support staged firmware upgrades and your backend tolerates mixed protocol versions. A dual-stack gateway makes this safe by decoupling each firmware upgrade from the backend. Group upgrades by vendor and site so you validate one variable at a time.
What breaks most often during migration?
Three things dominate: real hardware behaving unlike the OCTT, certificate lifecycle handling under Security Profile 2, and incorrect one-to-one message mapping between 1.6 and 2.0.1. The fix for all three is a representative pilot validated against real sessions and real billing output before you scale a rollout.


