How Infomaze moved a 10-year-old wealth management portal off .NET Framework 4.5 while 300 advisers and 4,200 clients kept using it every day.
Meridian Wealth Management had been running their client portal on .NET Framework 4.5 since 2013. For most of that decade it had worked well enough. It handled client portfolio views, document storage, adviser notes, scheduled reporting, and the FCA compliance audit trail. When it was originally built, it was solid engineering.
By 2024 the cracks were showing. Page response times had crept up as the client base grew past 4,000. Third-party financial data providers had stopped publishing .NET Framework SDKs — their integrations now existed only in .NET Core packages the portal couldn't use. The developer who had maintained the system for five years had moved on, and finding contractors willing to work in the old codebase had become genuinely difficult.
Their CTO, Stuart Ramsay, had wanted to migrate for two years. Every UK agency he'd spoken to had proposed the same approach: build a new portal in parallel, run both systems for a while, then cut over in a planned maintenance window. Stuart had seen that approach go badly at a previous employer. A cutover migration means two systems in sync, a high-pressure launch night, and a rollback that's never as clean as the planning assumes.
Parallel rebuild means two live systems. As the old system keeps taking real data, you have a synchronisation problem. The longer the parallel period runs, the more complex the final cutover becomes. And if something breaks on launch night, rolling back means losing everything written to the new system during the cutover window.
The portal generated regulatory compliance reports and held a complete client interaction audit trail. A gap in audit records — even a short one during a maintenance window — creates a regulatory problem. The FCA doesn't accept 'we were migrating' as an explanation for missing records.
We proposed the strangler fig pattern applied to a .NET Framework monolith. Rather than building a parallel system and cutting over, we would migrate the portal module by module while the existing system stayed live. At every point during the 14-week project, the portal was running a mix of old and new code. Users noticed nothing different. When the last module migrated, the legacy server was retired.
The pattern works by placing a routing layer in front of the existing application. New and migrated modules are served by the .NET 8 application. Everything else still routes to the legacy .NET Framework server. The legacy side handles less and less as the migration progresses, until it handles nothing.
// The routing layer — how it worked in practice
All requests → Nginx reverse proxy (deployed week 1)
if module in migrated_modules:
route → .NET 8 Azure App Service
else:
route → Legacy .NET 4.5 IIS Server
Week 0: migrated_modules = []
Week 4: migrated_modules = [
'auth',
'session'
]
Week 7: migrated_modules = [
'auth',
'session',
'portfolio_view',
'client_data'
]
Week 14: migrated_modules = ['all']
// Legacy IIS retired
The first thing we do on any data project is spend time with the actual data before agreeing to a scope. In this case, that meant two days on-site in the West Midlands — one day with the production team, one day with finance.
SAP Business One had solid transaction data going back several years. But the way it was being used meant that several key fields were inconsistently populated. Some production orders had completion timestamps. Some didn't. The quality tracking sheet, maintained on a shared drive, had been through three different formats in four years and had columns that meant different things depending on when the row was entered.
We came back with an honest assessment: a clean Power BI dashboard was achievable, but the data quality issues in SAP needed to be addressed first — otherwise we'd be visualising unreliable numbers more attractively. That conversation took some back and forth. Nobody likes being told their data is messy. But they agreed, and the project was better for it.
Before writing a line of .NET 8 code, we spent two weeks on a codebase audit. We don't quote a migration timeline without reading the code first — the audit is where the surprises live, and surprises mid-project are expensive.
| Area | Before | → | After (.NET 8) |
|---|---|---|---|
| Runtime | .NET Framework 4.5 — EOL, no new features | → | NET 8 LTS — active development, modern APIs |
| Deployment | IIS on-premise Windows Server — manual deploy | → | Azure App Service — auto-scaling, CI/CD pipeline |
| Auth | Forms Authentication + sticky session state | → | ASP.NET Core Identity + JWT + Azure Redis cache |
| Data access | Raw ADO.NET SQL in 34 controller methods | → | Entity Framework Core 8 — typed, testable, clean |
| File storage | On-premise file share · 340GB · no CDN | → | Azure Blob Storage — geo-redundant, CDN-backed |
| Scheduling | Thread.Sleep() timing loops — fragile | → | IHostedService + Quartz.NET — cancellable, reliable |
| Compliance | Third-party DLL · no source · vendor gone | → | Rebuilt natively · FCA spec validated · owned code |
| Page load | 4.1s average (portfolio view) | → | 1.4s average — 68% improvement |
| 3rd party SDKs | Multiple providers dropped .NET Framework support | → | All modern financial APIs now accessible |
| Downtime | Dreaded by the business for two years | → | Zero hours across 14-week migration |