Case study

Legal Compliance Platform

A Swiss legal-compliance SaaS stuck on non-scalable infrastructure, where every deployment meant downtime. Complex business rules, outdated user interface. How we designed the scalable, cloud-native, modernised system with zero-downtime replacement.
Diverse development team collaborating overhead around table with laptops, sketches, and mobile devices during brainstorming session

540 customers, 6,000 users, and a rewrite with no data migration

Sector Legal compliance SaaS · Market Switzerland · Period ~5 years · Role Development and maintenance partner, modernisation architecture

The challenge

A multi-tenant legal-compliance platform, live since 2014, used by Swiss industrial groups, hospitals, utilities and importers. It tracks legal obligations across 14 regulatory domains at federal, cantonal and municipal level, assigns accountability to specific sites and people, and runs the scheduled work that keeps all of it current.

After eleven years the system carried its age in a way you could feel from the outside.

During the 5 year period, EonIdeas was sole maintainer of the system: issue handling, new features implementation, infrastructure maintainance, defining requirements together with customer.

It ran as a single instance. The architecture was stateful, so a second instance couldn't simply be started alongside the first. That one fact set the ceiling on everything else: the platform could not scale horizontally under load, and it had no redundancy — one instance failing meant the service was down for all 541 customers at once. For a compliance system whose users have regulatory deadlines, that is not a theoretical risk.

Every deployment took the platform down. With only one instance to upgrade, there was no way to ship a release without an outage — which meant releases could only run at night, in the hours when nobody was using the system. That shaped how the product evolved, not just how it was operated: releases became rare, large and risky, the opposite of what you want on a system carrying a decade of compliance logic, and every one of them cost someone a night.

On top of that, the commercial UI framework the system was built on had become the constraint on what could be built at all, the .NET Framework stack limited what could be added, and the database had grown to 76 tables and 203 foreign-key relationships holding a decade of encoded compliance logic that could not simply be discarded.

Customers in this segment do not tolerate migration risk. Their audit trail is the product.

 

Overhead view of diverse professionals collaborating on project with laptops, notes, and planning documents

What we did

Two jobs in parallel: keep the live system dependable, and design a way out that doesn't require a big bang.

On the live system, that meant the unglamorous work that keeps a regulated platform trustworthy - a hierarchical permission model across nine roles from system administrator to auditor to compliance task owner, four language versions, and the scheduled jobs the service quietly depends on: customer status checks every five minutes, weekly compliance evaluations, nightly legal-decree imports, monthly newsletters, daily reminders on outstanding compliance actions.

On the modernisation, we authored the system architecture for the rewrite and the effort estimate behind it. The central decision was to preserve the existing SQL database untouched and replace everything above it. That single choice removes data migration - the largest source of risk in any legacy rewrite - from the project entirely.

Above the preserved database: a Spring Boot 3 backend on Java 21, an Angular 19 frontend using signals and standalone components, a modern data grid replacing the obsolete commercial one, Prometheus and Grafana for observability, all containerised behind Nginx as reverse proxy and API gateway.

The decisions that matter, though, are the ones that break the single-instance ceiling:

Stateless authentication. JWT-based, with no server-side session, so any instance can serve any request. This is the change that makes everything below it possible.

Shared state moved out of the application. Redis holds sessions and cached queries, so instances share state instead of owning it.


Event-driven, with the slow work off the request path. RabbitMQ carries report generation, email, and compliance notifications as asynchronous events rather than blocking work inside a request. A heavy PDF export no longer occupies a thread that a user is waiting on, and the components that produce and consume that work scale independently.


Every service runs as a container. The architecture was designed cloud-native from the start, but deliberately not tied to a cloud: the same containers run on the customer's own hardware or in any cloud environment, which matters when your customers are Swiss compliance departments and some of them will not accept anything else. Deployment target becomes a decision the client can revisit later rather than one baked into the design.


Horizontally scalable, with rolling deployments. With no state in the application, instances become interchangeable: run as many as the load requires behind the reverse proxy, lose one without losing the service, and ship a new version by rolling instances one at a time while the others keep serving. The release stops being an outage.

A pipeline that earns the right to deploy that often. Removing the downtime only helps if you trust what you are shipping, so we designed the CI/CD pipeline alongside the architecture: every code change runs unit tests, integration tests and end-to-end tests, and a deployment is followed by smoke tests against production itself. A release that fails a gate never reaches users; one that passes has been checked where it actually runs. Deploying more often is what makes each change small, and small changes are what make a compliance platform safe to evolve.

The night-time release window was the symptom. Non-scalable, stateful infrastructure was the disease. Removing it is what turns "we upgrade at 2am and hope" into a release during business hours with users still on the system.


The estimate has been presented to customer, broken down screen by screen, with the risks named rather than buried.  Design targets were set at 1,000 concurrent users, 99.5% availability and sub-500ms API response at the 95th percentile.

Overhead flat-lay of development documentation, printed spreadsheets, wireframes, laptop, and coffee on workspace table

What five years of context is worth

By the end of the engagement we knew the system better than anyone outside the client's own building - the 76-table schema, the decade of compliance logic encoded in it, and the reason each piece was there. That changes what the relationship is for.


We often got questions: is this feasible, what will it cost, what will it break, is the product even the right place to solve it? We answered those as a partner who already knew the constraints rather than as a vendor reading a ticket - and a good part of the value we delivered was in the requirements we talked the client out of, or reshaped into something cheaper and safer before a line of code was written.


The same applied to problems. A system with that much history can't be picked up from documentation, and that accumulated knowledge was a large part of what the engagement actually delivered.


The engagement ran in German throughout - requirements, documentation, the legal source material the platform ingests, and day-to-day correspondence with the client. One of our co-founders is a fluent German speaker, so none of it needed translating and none of it was lost in translation.

 

Result

A platform serving 541 customers and over 6,000 active users, kept in production throughout the engagement - and a modernisation architecture that removes the three constraints the business actually felt: no horizontal scaling, no redundancy, and no way to deploy without downtime - while staying deployable either on the client's own infrastructure or in the cloud.

Delivered with a detailed, screen-level estimate the client can execute or put out to tender, and with data-migration risk designed out of it.

The concurrency, availability and latency figures above are the design targets set in the architecture, not measured production results.

Stack: ASP.NET MVC · Entity Framework 6 · MS SQL Server → Spring Boot 3 / Java 21 · Angular 19 · Redis · RabbitMQ · Docker · Nginx · CI/CD with automated test gates · Prometheus + Grafana · on-premise or cloud.

Client name and reference available on request under NDA.

Sitting on a system that works but can't move?

Tell us what's stuck and we'll give you an honest read on what it would take to move it - a rewrite, a staged migration, or two or three well-placed changes.