Designing a Scalable OCPP server


What is OCPP?

OCPP, short for Open Charge Point Protocol, is like the universal language of EV charging. It sets the standard for how charging stations talk to central systems, enabling functions like monitoring, management, billing, and even integration with third-party systems. This open-source protocol isn’t just a buzzword — it’s backed by a robust community of vendors and manufacturers, making it a widely adopted and trusted solution.

How OCPP Works

At its core, OCPP operates through two main components: the protocol itself and its profiles. The protocol defines the communication rules between charge points and central servers, while profiles determine what data gets exchanged. Picture this: a driver plugs in their EV at a charging station. OCPP kicks into action, transferring driver details to the central server for authentication and initiating the charging process. Simultaneously, the station communicates key data like energy usage and status back to the central system for billing and maintenance purposes.


Chargers communicate with the OCPP or CMS server using the same OCPP protocol. They are equipped with small hardware, similar to a Raspberry Pi, where firmware code is written. This code is responsible for monitoring and transferring data about specific charging sessions to the OCPP server. Additionally, it accepts commands such as startTransaction and stopTransaction from the standard OCPP server to initiate a charging session.

Chargers also communicate with the Battery Management System (BMS) of electric vehicles (EVs) using the ISO 15118–2 digital communication protocol can see in fig 1.1, which implements various features. This protocol facilitates seamless communication between the charger and the EV’s BMS, ensuring efficient and coordinated charging processes:

ISO 15118–2 Protocol

Design Tradeoff

Now that we both have established some foundational concepts and are on the same page, let’s delve into the implementation aspect from a - software engineering perspective. To build an OCPP server, we need to consider various factors.

Firstly, we should brainstorm about the implementation details, such as choosing the appropriate design pattern — whether to opt for a client-server model, an event-driven architecture, or a stateless or stateful approach. Additionally, we need to decide on the programming language, protocol (e.g., HTTPS, WebRTC, WebSocket, or a queue-based implementation), and database technology. These choices will shape the robustness, scalability, and efficiency of our OCPP server.

Before diving into implementation specifics, let’s consider a scenario. To initiate a charging session, a user triggers a command from the app, which sends a request to the OCPP server. The OCPP server then establishes communication with the charger, instructing it to begin the charging session.


Now, let’s visualize how your system might look if you opt for a client-server model:

Roughly 5 http connection and state of chrging session csn be varry but lets fix this for 50(anyhow you going to chrge your veichle more than 50second). Starting the charger from the user’s end, the charger begins charging from its side. The charging session’s state is updated from the user’s end every 1 or 2 seconds. When the charging is complete, the user ends the session, and the session is ended from the charger’s side as well.

However, using this model can lead to several drawbacks and overheads, especially due to the multiple HTTPS calls involved. Here are some potential issues:

Increased Cost

Each HTTPS call incurs a cost, especially if using external services or APIs. With roughly 50 HTTP connections per session, this cost can add up significantly over time.

HTTP Header Overhead and Handshaking

Each HTTP request and response involves the exchange of headers, which contain metadata about the request and response. This header overhead can become significant, especially when multiple HTTP connections are made within a short period. Additionally, establishing a new connection for each HTTP request requires the overhead of handshaking, where the client and server negotiate parameters and establish the connection. Even when the client and server remain the same, this repeated handshaking process adds to the overall latency and resource consumption, impacting the speed and efficiency of the charging process. Implementing strategies like connection pooling, persistent connections, or using protocols optimized for low overhead, such as WebSocket, can help alleviate these issues and improve performance.

Impact on Latency and Speed

Multiple HTTPS calls introduce latency and can slow down the overall charging process. This delay can be noticeable, especially in scenarios where rapid responses are required, such as managing real-time charging sessions or handling high volumes of transactions.

Complexity in Management

Managing and coordinating multiple HTTPS calls can add complexity to the system architecture. It requires robust error handling, retries, and monitoring mechanisms to ensure smooth operation and reliability.

Resource Utilization

Each HTTPS call consumes resources, including network bandwidth, server processing power, and memory. In situations with a large number of concurrent sessions, this can strain the system and impact overall performance.

To mitigate these drawbacks, optimizing the HTTPS calls, implementing caching mechanisms, reducing unnecessary data transfers, and considering alternative communication protocols or optimizations can help improve efficiency and reduce overhead.

Statefull system

In the previous model, we encountered challenges due to the repeated use of HTTP connections, which led to costly handshaking mechanisms and increased header lengths. However, let’s consider a more efficient approach using an event-driven and stateful system, leveraging the benefits of WebSocket technology.

In this optimized model, we acknowledge that our OCPP server and charger remain the same entities throughout the process. By adopting a stateful system, we can persist the connection between the client (user or charger) and the server (OCPP server). This persistence eliminates the need for frequent handshakes and reduces the overhead caused by lengthy headers.

Now, let’s talk about using


Duplex Mechanism

WebSocket’s duplex mechanism allows for simultaneous data transfer from both ends over a single connection. This bidirectional communication capability is crucial for real-time updates and efficient interaction between the user and the server.

Latency and Speed

By maintaining a persistent connection, WebSocket significantly reduces latency compared to traditional HTTP connections. The elimination of repeated handshaking and header overhead results in faster data transmission, enhancing the overall speed and responsiveness of the charging process.

Fewer Connections

WebSocket’s persistent nature means fewer connection establishment overheads. Unlike HTTP, where each request requires a new connection and handshake, WebSocket maintains a continuous connection, leading to fewer resources consumed and improved efficiency.

Technical Details

WebSocket operates over TCP, providing a reliable and full-duplex communication channel. It uses a lightweight protocol that minimizes overhead, making it ideal for real-time applications like EV charging management. WebSocket’s support for binary data transmission and built-in error handling further enhances its suitability for handling EV charging sessions seamlessly.

By using WebSocket within an event-driven and stateful architecture, we can optimize the communication between the charger, user, and OCPP server. This approach not only reduces overhead and latency but also ensures a smoother and more responsive charging experience.

Choosing Database

Choosing a scalable database like ScyllaDB for a real-time EV charging management system with WebSocket technology offers several advantages:

Real-Time Performance

ScyllaDB’s high-throughput and low-latency capabilities make it ideal for handling real-time data streams and rapid updates in an event-driven system.

Horizontal Scalability

ScyllaDB’s distributed architecture allows for seamless horizontal scaling by adding more nodes, ensuring the system can accommodate growing data volumes and user traffic.

Flexible Schema

With support for flexible schemas, ScyllaDB enables easy adaptation to evolving data structures and simplifies integration with WebSocket-based real-time data streams.

High Availability

ScyllaDB’s fault-tolerant design and automatic sharding ensure high availability and reliability, crucial for mission-critical applications like EV charging management.

In summary, ScyllaDB provides the performance, scalability, flexibility, and reliability needed for a modern, real-time EV charging system utilizing WebSocket technology.

System Design

Designing a Detailed System Architecture for Real-Time EV Charging Management

WebSocket Communication Layer

Implement WebSocket protocol for real-time bidirectional communication between EV chargers, users, and the OCPP server. Use WebSocket libraries and frameworks like Socket.IO for efficient WebSocket management and event handling.

ScyllaDB for Data Storage

Utilize ScyllaDB as the primary database for storing real-time charging session data, user information, and system configurations.

Redis for Scaling and Caching

Integrate Redis as a caching layer for scaling WebSocket connections and maintaining session states. Use Redis Pub/Sub for real-time notifications and event broadcasting to connected clients

Stateful API Gateway

Design a stateful API gateway using Redis to manage session states, authenticate users, and handle API requests. Utilize Redis data structures like Hashes and Sets for storing session information, user tokens, and access control lists (ACLs).

Kafka for Ultra-Scalable Event Processing

Integrate Kafka as a message broker for handling high-throughput event streams and data processing. Use Kafka topics for event-driven architecture, allowing components to publish and subscribe to relevant events.

Microservices Architecture

Design the system using a microservices architecture for modularity, scalability, and fault isolation. Create microservices for user management, charging session control, billing, monitoring, and analytics, each interacting through Kafka and Redis for data synchronization and event-driven communication.

Load Balancing and Auto-Scaling

Implement load balancing using Nginx or a similar tool to distribute WebSocket connections and API requests across multiple servers. Configure auto-scaling policies based on metrics like CPU utilization, WebSocket connection count, and API request rate to dynamically adjust resource allocation and handle traffic spikes efficiently.


Current Architecture Design

Now that we have a clear understanding of our technology, tools, and architecture, let’s simulate the entire system using a straightforward example, step by step. Imagine planning a road trip from start to finish.

Starting a Charging Session

The user initiates a charging session through the mobile app or web interface, sending a request to the OCPP server via HTTPS or WebSocket API endpoints.

OCPP Server Interaction

Upon receiving the request, the OCPP server processes the command and verifies the user’s credentials and authorization for the charging session. The OCPP server updates the charging session status in ScyllaDB, indicating that a new session is initiated and the user is authorized to charge.

WebSocket Communication

The OCPP server establishes a WebSocket connection with the designated charger identified for the session, using the persistent connection pool managed by Redis for efficient connection management. Data related to the charging session, such as start command, charging parameters, and user authentication, is sent over the established WebSocket connection to the charger.

Charger Starts the Session

The charger receives the data from the WebSocket connection and verifies the session details and authorization. Upon successful validation, the charger starts the charging session, initiating the flow of electrical power to the EV.

Session Feedback and Status Update

The charger sends real-time updates and feedback about the charging session, such as current charging rate, energy consumption, and battery status, back through the WebSocket connection to the OCPP server. The OCPP server processes and updates the session status in ScyllaDB, continuously tracking and recording session data for monitoring and analytics purposes.

Publishing to Kafka

Key events and data updates related to the charging session, such as session start, stop, charging status changes, and energy consumption milestones, are published as messages to specific Kafka topics. Kafka acts as a centralized message broker, ensuring reliable delivery of messages and providing durability and fault tolerance.

Microservices Consumption

Multiple microservices within the system architecture subscribe to relevant Kafka topics, consuming and processing the published messages. For example, a billing microservice calculates and records charging costs based on energy consumption data received from Kafka messages. Another monitoring microservice tracks charging session metrics and generates real-time alerts or notifications for system administrators or users

Yes, this was it. It was all that I understood and my approach for such a system from a software engineer’s perspective.

Now, there are a lot of ways and tools you can use for building an EV charging infrastructure system that can be more scalable and robust.

My take on the EV industry from a software point of view is that it is still very immature. Many things designed or currently being developed are mostly from a hardware or business point of view, which is good. However, at the end of the day, you’re dealing with abstract software systems, which should be the prime focus of institutions.

There are very few experts who know the system from end to end, and even fewer who want to know. There is a scarcity of good blogs and reading materials, and the ones available are often not structured.

Also, I am developing an open-source OCPP server from scratch that anyone can use and build upon. It will take time, so stay tuned to my GitHub, which you can find [here](siddharth github). You can follow me on GitHub to track my progress.

Read Previous

How Discord Used Rust to Scale Elixir to Millions

Go to top