Skip to content
BlogUpdated 13 min read

How to Build a CPMS: Complete Architecture Guide

Build a production CPMS from scratch: WebSocket servers, OCPP message routing, authorization, smart charging, OCPI roaming, and scaling 6 core components.

How to Build a CPMS: Complete Architecture Guide
On this page

Quick answer: Building a CPMS means engineering a WebSocket server, OCPP message router, device registry, authorization service, transaction engine, billing, smart charging, and OCPI gateway. Implement OCPP step by step, starting with connection management, then scale connections and meter-value storage. Build it when charging is your core product, typically once you operate at large fleet scale.

Building a CPMS (Charging Station Management System) from scratch is a significant engineering undertaking. It requires deep understanding of the OCPP protocol -- maintained by the Open Charge Alliance -- WebSocket infrastructure, real-time data processing, and the operational realities of EV charging networks. But for companies where charging is a core product differentiator, building your own CPMS provides unmatched control over features, integrations, and competitive advantage.

This guide walks through the architecture, technology choices, implementation steps, and scaling considerations for building a production-grade CPMS.

Why Build a CPMS Instead of Buying One?

Building your own CPMS makes sense in specific circumstances. It does not make sense for everyone.

Build When:

  • Charging is your primary product, not a supporting feature
  • You need deep integration with proprietary systems (custom billing, fleet management, energy trading)
  • Your business model requires features that no existing CPMS provides
  • You plan to operate at a scale where per-charger licensing costs exceed engineering investment
  • You need full control over data, security, and compliance

Buy When:

  • Charging supplements your core business (hospitality, retail, real estate)
  • You need to deploy within weeks, not months
  • Your team lacks OCPP protocol and WebSocket infrastructure expertise
  • You are managing fewer than 1,000 chargers

The break-even point varies widely. Most companies find that building becomes cost-effective only at large fleet sizes, once recurring per-charger licensing costs outweigh the upfront engineering investment -- the exact threshold depends on commercial CPMS pricing and the customization you need.

What Does a CPMS Architecture Look Like?

A production CPMS consists of several interconnected components. Each serves a distinct function, and the interfaces between them determine your system's reliability and extensibility.

Core Components

Component Responsibility Key Requirements
WebSocket Server Manage persistent connections with charge points High concurrency, low latency, connection state tracking
Message Router Parse OCPP messages and dispatch to handlers Protocol version awareness, message validation, handler registry
Device Registry Track charge points, connectors, and their state Real-time status, configuration storage, firmware tracking
Authorization Service Validate driver credentials (RFID, tokens, certificates) Low latency (<200ms), local auth list management, group authorization
Transaction Engine Manage charging session lifecycle Idempotent operations, meter value aggregation, billing event generation
Billing Engine Calculate costs and process payments Tariff management, CDR generation, payment gateway integration
Smart Charging Engine Compute and distribute charging profiles Real-time optimization, grid constraint awareness, profile stacking
OCPI Gateway Enable roaming with external networks OCPI 2.1.1/2.2.1 compliance, partner credential management, CDR exchange
Monitoring and Alerting Track system health and charger status Dashboards, anomaly detection, incident notification

High-Level Architecture

                    Load Balancer (sticky sessions)
                           |
              +------------+------------+
              |            |            |
         WS Server    WS Server    WS Server
              |            |            |
              +-----+------+------+----+
                    |             |
              Message Bus (Redis/Kafka)
                    |             |
    +-------+-------+-------+--------+-------+
    |       |       |       |        |       |
  Auth   Txn    Smart    Device   Billing  OCPI
  Svc    Engine  Charge   Registry Engine   Gateway
    |       |       |       |        |       |
    +-------+-------+-------+--------+-------+
                    |
              Database Layer
    (PostgreSQL + Redis + TimescaleDB)

Which Technologies Should You Choose?

WebSocket Libraries

The WebSocket server is the most performance-critical component. Your choice of language and library directly impacts connection capacity and message throughput.

Language Library Strengths Considerations
Node.js ws or uWebSockets.js Excellent ecosystem, fast prototyping, native JSON handling Single-threaded event loop; use clustering for CPU-bound work
Go gorilla/websocket or nhooyr/websocket High concurrency with goroutines, low memory per connection Smaller OCPP ecosystem; more protocol-level code to write
Java Spring WebSocket or Netty Enterprise tooling, strong typing, mature ecosystem Higher memory footprint per connection, more boilerplate
Rust tokio-tungstenite Maximum performance, minimal memory Steepest learning curve, smallest OCPP ecosystem
Python websockets or FastAPI Rapid development, data science integration Lower throughput than compiled alternatives; viable for smaller scales

For most teams, Node.js with ws or Go with gorilla/websocket offers the best balance of development speed, performance, and ecosystem support.

Databases

A CPMS has distinct data access patterns that benefit from a polyglot persistence strategy.

Data Type Recommended Database Reasoning
Charge points and config PostgreSQL Relational data with complex queries, strong consistency
Transactions and CDRs PostgreSQL ACID compliance for financial data, complex reporting queries
Active sessions Redis Sub-millisecond reads for real-time authorization and session state
Meter values TimescaleDB (PostgreSQL extension) Time-series optimized storage, automatic partitioning, compression
OCPP message logs Elasticsearch or ClickHouse Full-text search across millions of messages, log analysis
Charging profiles Redis + PostgreSQL Redis for active profiles (fast reads), PostgreSQL for history

Starting with PostgreSQL for everything is a valid approach for early-stage development. Introduce specialized databases as specific performance bottlenecks emerge.

How Do You Implement OCPP Step by Step?

Step 1: WebSocket Server

Build the connection management layer first. This is the foundation everything else depends on.

Key requirements:

  • Accept WebSocket connections with OCPP subprotocol negotiation (ocpp1.6, ocpp2.0.1)
  • Extract charge point identity from the URL path (e.g., /ocpp/CP001)
  • Maintain a connection registry mapping charge point IDs to active WebSocket connections
  • Implement WebSocket Ping/Pong for connection health monitoring
  • Handle disconnection detection and cleanup
Connection URL pattern:
  wss://your-CPMS.com/ocpp/{chargePointId}

Subprotocol negotiation:
  Client requests: ocpp1.6, ocpp2.0.1
  Server selects: ocpp1.6 (or whichever version to use)

Step 2: BootNotification Handling

BootNotification is the first OCPP message every charger sends after connecting. Your handler must:

  1. Parse the charge point vendor, model, serial number, and firmware version
  2. Decide whether to accept, reject, or set the charger to pending status
  3. Return the current time (chargers use this for clock synchronization) and heartbeat interval
  4. Register or update the charge point in the device registry
  5. Trigger any pending configuration changes or firmware updates for this charger

Accept unknown chargers in development; require pre-registration in production. The Pending status is useful for chargers that need manual approval or additional configuration before going live.

Step 3: Authorization

Every charging session begins with authorization. Build the authorization service to handle multiple methods:

  • RFID tags: Look up idTag in the database, check expiry and group membership
  • Remote start: The CPMS initiates charging via RemoteStartTransaction (driver uses an app)
  • Local Auth List: Maintain a cached list of authorized tags on the charger for offline operation
  • Plug and Charge: ISO 15118 certificate-based authorization (OCPP 2.0.1) -- see our ISO 15118 Plug and Charge guide for details

Authorization latency directly impacts driver experience. Target sub-200ms response times. Use Redis caching for frequently used tags and implement the Local Authorization List for resilience during network outages.

Step 4: Transaction Management

Transactions are the core business object of a CPMS. Handle them with the reliability they demand.

Transaction lifecycle (OCPP 1.6):

  1. Charger sends StartTransaction with connectorId, idTag, meterStart, and timestamp
  2. CPMS validates authorization, creates transaction record, returns transactionId
  3. Charger sends periodic MeterValues with energy readings, power measurements, and SoC
  4. Charger sends StopTransaction with meterStop, timestamp, and stop reason
  5. CPMS finalizes transaction, calculates cost, generates billing record

Critical implementation details:

  • transactionId assignment must be unique and sequential
  • Handle duplicate StartTransaction messages idempotently (network retries)
  • Process MeterValues asynchronously to avoid blocking the WebSocket handler
  • Implement transaction recovery for sessions interrupted by disconnection
  • Store raw meter values alongside computed totals for audit purposes

Step 5: Smart Charging

Smart charging adds real-time power management to your CPMS. Start with basic load balancing and iterate toward advanced optimization.

Implementation progression:

  1. Static load balancing: Set a fixed ChargePointMaxProfile per site that divides capacity equally
  2. Dynamic load balancing: Integrate with smart meters to adjust profiles based on real-time site consumption
  3. Priority-based allocation: Factor in driver priority, departure time, and SoC to optimize distribution
  4. Peak shaving: Monitor demand charges and throttle charging during peak windows
  5. Demand response: Integrate grid operator signals for external constraint management

Charging profiles use a stack-level priority system. Higher stack levels override lower ones. Ensure your implementation correctly composites overlapping profiles, which is one of the most error-prone areas of OCPP smart charging.

Step 6: OCPI Integration

OCPI (Open Charge Point Interface), maintained by the EVRoaming Foundation, enables roaming -- allowing drivers from other networks to use your chargers and vice versa.

Core OCPI modules to implement:

Module Purpose
Locations Publish your charge point locations, capabilities, and real-time status
Sessions Share active charging session data with the roaming partner
CDRs Exchange Charge Detail Records for billing reconciliation
Tariffs Publish pricing information for roaming drivers
Tokens Exchange driver authorization tokens between networks
Commands Allow remote start/stop from partner networks

OCPI is a REST API (not WebSocket), so it integrates as a separate service alongside your OCPP-facing infrastructure. At minimum, implement Credentials (mandatory for all OCPI connections), Locations, Tokens, Sessions, and CDRs for a functional roaming connection. You cannot do roaming with just Locations and CDRs — Tokens are required for authorization exchange, and Sessions for real-time tracking.

How Do You Scale a CPMS?

WebSocket Connection Scaling

Each WebSocket connection consumes memory, and the exact per-connection footprint depends heavily on your language and library choices. Across tens of thousands of chargers, connection state alone adds up to a meaningful memory budget you need to plan for.

Horizontal scaling strategy:

  • Deploy multiple WebSocket server instances behind a load balancer
  • Use sticky sessions (source IP or cookie-based) so each charger always connects to the same instance
  • Implement a shared session store (Redis) so any instance can handle CPMS-initiated commands
  • When a charge point reconnects, it may hit a different instance; design for this

Database Scaling

MeterValues are the highest-volume data in a CPMS. A single charger sending frequent meter values generates hundreds of thousands of rows per year, so a fleet of tens of thousands of chargers can produce billions of rows annually.

Scaling approaches:

  • Use TimescaleDB for automatic time-based partitioning and compression
  • Implement data retention policies (raw values for 90 days, aggregated values for 7 years)
  • Separate read and write workloads with read replicas
  • Partition transaction tables by date range
  • Archive completed transactions to cold storage after billing reconciliation

Message Throughput

A production CPMS must handle bursts of simultaneous messages. Common burst patterns:

  • Morning peak: Hundreds of chargers sending StatusNotification as drivers arrive at work
  • CPMS restart: All connected chargers send BootNotification simultaneously after reconnection
  • Firmware update: Mass FirmwareStatusNotification messages during a fleet-wide update

Use a message queue (Redis Streams, Apache Kafka, or RabbitMQ) between the WebSocket layer and message handlers to absorb these bursts without dropping messages or overloading downstream services.

How OCPPLab Accelerates CPMS Development

Building a CPMS without simulated chargers means you cannot test until you have physical hardware. This creates a painful feedback loop: code for days, deploy, connect a charger, discover a bug, repeat.

OCPPLab eliminates this bottleneck by providing virtual charge points that behave like real chargers throughout your entire development cycle:

  • Develop against realistic behavior: Connect virtual chargers to your CPMS from day one. Test BootNotification handling before you write transaction logic.
  • Validate every message flow: Exercise all OCPP message types including edge cases (offline authorization, partial meter values, interrupted transactions) without waiting for specific charger hardware.
  • Load test early: Spin up 1,000 virtual chargers to find connection management bugs, database bottlenecks, and memory leaks before they surface in production.
  • Test smart charging: Simulate multiple EVs with different battery levels, power demands, and departure times to validate your load balancing algorithms produce correct charging profiles.
  • Regression testing: Build automated test suites that run virtual chargers through critical scenarios on every deploy, catching OCPP protocol regressions before they reach production.
  • Multi-version testing: Test against both OCPP 1.6 and 2.0.1 charger behavior simultaneously, ensuring your dual-version CPMS handles protocol differences correctly.

Teams using OCPPLab report cutting their CPMS development cycle by months because they can test continuously rather than waiting for hardware availability.

Frequently Asked Questions

How long does it take to build a CPMS?

A minimum viable CPMS supporting BootNotification, Authorization, and basic transaction management takes a few months for a small team of two to three engineers. A production-grade CPMS with smart charging, OCPI roaming, billing, and monitoring typically takes considerably longer -- on the order of a year or more. Ongoing maintenance, OCPP compliance updates, and feature development are continuous after launch.

What team do I need?

At minimum: 1-2 backend engineers with WebSocket and real-time systems experience, 1 engineer with OCPP protocol expertise (or willingness to deeply study the specification), and 1 DevOps/infrastructure engineer for deployment and monitoring. For a full-featured CPMS, add frontend engineers for the operator dashboard, a data engineer for analytics, and QA engineers for protocol compliance testing.

Should I support OCPP 1.6 and 2.0.1?

Yes. OCPP 1.6 is still the most widely deployed version, and many chargers in the field will run 1.6 for years. OCPP 2.0.1 is required for new installations in many markets and provides critical features (improved transaction model, device management, ISO 15118 integration). Build your message router to handle both versions from the start, with version-specific message handlers that share common business logic.

What is the biggest technical challenge?

WebSocket connection management at scale. Maintaining tens of thousands of persistent connections, handling reconnection storms gracefully, ensuring message ordering, and routing CPMS-initiated commands to the correct server instance are all non-trivial engineering problems. Most teams underestimate this and focus too early on business logic.

Can I use an existing OCPP library instead of building from scratch?

Absolutely. Libraries like ocpp (Python), node-ocpp (Node.js), and various Java OCPP libraries handle protocol-level concerns (message parsing, validation, routing) so you can focus on business logic. Evaluate libraries for protocol completeness, maintenance activity, and community size before committing.

How do I handle charger firmware differences?

Different charger manufacturers interpret the OCPP specification differently. Some send optional fields, others omit them. Some use slightly different enum values or timestamp formats. Build your message handlers defensively: validate but accept variations, log discrepancies, and maintain a charger compatibility matrix. Testing against multiple virtual charger configurations in OCPPLab helps identify these differences before production deployment.

Next step

Move from article research into protocol coverage, a concrete testing use case, or the product itself.

Test your OCPP implementation today

Deploy 1000+ virtual charge points in minutes. No hardware needed.

Get OCPP & EV charging insights

Protocol updates, testing best practices, and industry news. No spam.

Read more

Related articles

Test your CPMS today. Ship faster tomorrow.

Book a 30-minute demo and run a real scenario against your stack with our OCPP simulator. Or start free and launch your first virtual EV charger in minutes.

  • No credit card required
  • First test in minutes
  • Contact sales for enterprise