ev charging management

May 2024 — December 2025

electric vehicle charging station project was a platform we started around mid-2024 and worked on for more than 1.5 years. there was already an existing monolithic system in the company, but we built a new microservice-based platform from scratch, independent from that structure. the goal was to manage charging stations, charge points, charging sessions, pricing, mobile app, and portal needs with a more flexible backend architecture.

for device communication, we used aws iot core. charging devices were communicating directly with aws iot core. we were consuming the messages coming into aws through sqs queues with consumer services and processing them inside our system.

we were writing the consumed messages into elasticsearch for logging and tracking purposes. to keep the latest status of the devices visible on the platform, we were also routing these messages to the related microservices through rabbitmq direct exchange.

users also needed to track their active charging sessions in real time from the mobile app and portal. for this, we were broadcasting related charge point messages through rabbitmq fanout exchanges. mobile and portal applications were connected to their own bff services through websocket, and they were receiving this message flow in real time.

we designed the system as tenant-based. different whitelabels could join the same platform with their own sub-operators, branding, logos, and user pools, while still using the same mobile application.

for authentication, we used duende identityserver. we separated user management by tenant and client, so different whitelabels could work with their own user pools. portal and mobile users could be kept in different user groups, but they could still access the charging stations and charge points they were authorized to see through the same tenant hierarchy.

for map listing, we used aws opensearch. since it is based on elasticsearch, it worked well for our nosql data needs. when a user opened the map, it allowed us to list all charging unit pins quickly.

services were communicating with each other through rabbitmq direct exchange. each microservice had its own database, and we used postgresql as the database.

we used redis for distributed cache. it had a critical role especially in charging start and stop flows. since these flows were mostly asynchronous, we used redis for idempotency and for matching the correct user, connector, and transaction.

in the charging start flow, we had to manage the relationship between charge point, connector, rfid card, and user correctly. by keeping temporary state in redis, we could match asynchronous device messages with the transaction created in our system. this helped us make sure that the charging session started on the correct connector and was assigned to the correct user transaction.

corebff was one of the central services in this flow. it handled requests from services like mobilebff and portalbff, collected data from other microservices synchronously when needed, and acted as an intermediate layer in device-related transaction flows. some messages coming from devices were listened to through lambda functions, and then the transaction information created in our system was sent back to the related device through corebff.