Replacing a monolith without putting operations at risk
At an energy supplier, market communication – registrations, deregistrations, meter readings – runs through a PHP monolith that is considered unmaintainable. It has to be replaced without operations grinding to a halt.
Move the sending and processing of market data out of the monolith – step by step, while the system keeps running.
New applications and libraries in Kotlin and Java with Spring Boot on AWS, built on a hexagonal architecture.
All market data is now sent through the new applications. In a load test, the aggregation processed 70,000 records in under a minute, and the monolith runs more stably.
- 70,000
- market data records aggregated in under a minute in a load test
- ≈ 10%
- of the monolith replaced
- 6
- libraries and applications built
A system nobody wants to touch
The monolith sends market messages to other market participants and aggregates market data. It is considered unmaintainable, and aggregating large volumes of data was an almost impossible task for it.
Replacing it in one go would have been too risky. So it is being replaced piece by piece: each new application takes over a clearly defined part.
Hexagonal – and a template for the department
I built the new applications on a hexagonal architecture: the domain logic knows nothing about databases or messaging. Adapters for AWS, PostgreSQL and interfaces are interchangeable and can be tested on their own.
The department now uses this structure as a template for further applications.
- 6 libraries and applications in Kotlin and Java
- Messaging via SQS and SNS, data in S3 and Aurora PostgreSQL
- Tests with Testcontainers, WireMock and LocalStack
Faster and more stable
All market data is now sent through the new applications, and they also handle its aggregation and summarization. About 10% of the monolith has been replaced, and the remaining part has been running more stably since.
In the first load test, the new aggregation processed 70,000 market data records in under a minute. For the legacy system, that was practically out of reach.
So the new system does not become the next legacy system
I upgraded the new applications from Java 21 to Java 25 and from Spring Boot 3 to Spring Boot 4, and introduced Renovate. Dependencies have been kept up to date automatically ever since.
- Kotlin
- Java 25
- Spring Boot 4
- AWS S3
- SQS
- SNS
- EKS
- Aurora PostgreSQL
- Terraform
- Kubernetes
- Flyway
- Testcontainers
- WireMock
- LocalStack
