Modernizing a legacy export workflow without stopping delivery
Replacing a monolithic, DLL-based calibration export workflow with an event-driven REST platform in C#/.NET, one boundary at a time, while calibration data kept shipping to customers.
Calibration data for e-motor and inverter software is managed in AVL CRETA and exported for software integration and delivery to vehicle manufacturers. At Valeo, that export ran through a monolithic workflow built on a DLL-based API, and that API was scheduled for deprecation. The workflow could not simply be switched off: calibration packages had to keep reaching customers on schedule.
The problem
- A hard deadline: the DLL-based API would stop working with future CRETA versions.
- Tight coupling: extraction, OEM-specific rules, file handling and reporting were intertwined, so every change was risky.
- Large artifacts: HEX, DCM and PAR files made synchronous processing slow.
- Several customers, several variants: each manufacturer needed its own export behavior.
The approach
1. A generated client instead of a hand-written one. I used Kiota to generate a typed C# client from the CRETA OpenAPI (Swagger) description. The new REST client replaced the legacy DLL before its deprecation, and regenerating it keeps it in step with the API.
2. A boundary around the legacy world. An anti-corruption layer and adapters translate between the external API model and our own domain model, so changes on one side don't spread to the other. A facade unifies authentication, session tokens and file routing.
3. One module per customer variant. A factory instantiates OEM-specific modules at runtime behind small, segregated interfaces. Supporting a new variant means adding a module, not editing the core.
4. Asynchronous and event-driven. Large artifacts are extracted with non-blocking I/O and processed concurrently. Synchronization between local storage and the central NAS is event-driven, with retries and exponential backoff for transient failures.
5. Incremental rollout with tests. The new layer was integrated into the existing WPF desktop application step by step, covered by NUnit tests in the CI pipeline, so delivery never stopped.
The result
- The legacy DLL dependency was replaced before it became a blocker; the platform is ready for CRETA v6+.
- Customer-specific behavior lives in isolated modules, which made changes smaller and safer.
- Large exports no longer block the user interface, and transient network problems recover automatically.
What I learned
- Generate what you can. A generated API client removes a whole class of integration bugs.
- Draw the boundary first. Once the anti-corruption layer existed, the rest of the modernization could happen behind it at our own pace.
- Modernize while delivering. Small, tested steps inside the existing application were slower to plan but much less risky than a big switch-over.