The problem
A single .NET Framework 4.7 monolith meant every release risked every domain, and a full deploy took about two hours of manual steps.
System architecture
flowchart LR
subgraph legacy ["Legacy monolith"]
legacy_0[".NET Framework 4.7 monolith"]
legacy_1["Manual deploy pipeline"]
end
subgraph extract ["Strangler cut"]
extract_0["First domain service on .NET 7"]
extract_1["Traffic router or gateway"]
extract_2[("Shared DB phase")]
end
subgraph platform ["Event and ops"]
platform_0[["RabbitMQ event bus"]]
platform_1["CI build and test"]
platform_2["Automated deploy to EC2"]
platform_3["AWS standard template"]
end
legacy_0 --> extract_1
extract_1 --> extract_0
extract_0 --> extract_2
extract_0 --> platform_0
platform_1 --> platform_2
platform_3 --> platform_2Key architecture decisions
Strangler split by domain, not big-bang rewrite
Run new .NET 7 services beside the monolith and shift traffic gradually.
A rewrite freeze would stall fixes for paying accounts.
Rejected Big-bang rewrite — rejected because risk and calendar were unacceptable.
Trade-off Temporary dual-run operational cost and shared-database coupling until a later cut.
Async end-to-end on I/O-bound paths
Use async through Web API and data access on hot paths; remove session affinity where possible.
Thread pool starvation under load was a recurring monolith pain.
Rejected Blocking .Result calls on legacy sync wrappers — rejected on new services after deadlocks in Framework hosting.
Trade-off Team retraining and careful audit of legacy call sites still on the monolith.
Standard AWS and CI template for new projects
One default EC2, security group, Docker Compose, and CI checklist cloned per project.
Each new engagement was re-inventing TLS and deploy steps.
Rejected Per-project custom infra — rejected after repeated week-long onboarding delays.
Trade-off Template drift must be owned; exceptions need written justification.
What I own, wrote, and delegate
Own
- Migration strategy and which domain to cut first
- CI/CD standardization and AWS onboarding template for new projects
- Technical point of contact for 5 enterprise accounts during migration windows
Wrote
- First extracted .NET 7 services and integration with the remaining monolith
- Event-driven paths where domains needed async integration
Delegate
- Per-account commercial negotiation and account management
Scale
- Monolith deploy about 2 hours before automation; about 15 minutes after CI/CD and smaller services
- New project AWS onboarding reduced from weeks to days with a shared template
- 5 enterprise accounts with me as technical point of contact for incidents
Boundaries
- Load improvement came in layers (async I/O, state out of process, cache, indexes, runtime upgrade), not a single magic number.
- Cutover was not a zero-downtime rolling deploy for every service.
What we watch in operation
Rules the design never breaks
- No single-domain deploy may require a full-monolith outage.
- Shared schema changes are coordinated; services do not silently fork data meaning.
- Enterprise accounts get a named technical contact during migration, not only ticket queues.
Broader application
- Legacy .NET Framework estates that must move without stopping revenue.
- Organisations standardising cloud onboarding across many projects.
- Teams learning microservices after years of monolith releases.