Technical scope & engineering decisions
.NET & architecture
.NET application architecture and implementation, from domain models and SQL queries to ASP.NET APIs. The work includes structuring business rules, keeping integrations compatible, and replacing legacy components in stages.
ASP.NET · SQL · DDD / CQRS
Technical scope
Domain boundaries and consistency
A domain boundary does not automatically require a distributed service.
Group business rules and data that must change in one transaction. Use DDD to model those rules and CQRS when reads and writes need different representations. Keep closely related operations in one application; split services when independent releases or scaling justify the added coordination and failure handling.
Contracts across application boundaries
A timeout leaves the outcome of a remote write uncertain.
Design APIs around validation, authorization, predictable responses, and compatibility with existing consumers. Set time limits for remote calls and make repeated writes safe through idempotency. For asynchronous work, track progress and handle duplicate messages. Reconciliation resolves records whose outcome remains uncertain after a timeout or interrupted exchange.
Modernization without a coordinated rewrite
Application rollback and data recovery are separate concerns.
Map dependencies, isolate a responsibility, and replace it behind an API that existing consumers can still use. Check behavior while old and new components coexist, then move consumers gradually. Plan data migration and write access explicitly: reverting application code cannot undo every change to stored data.
Design priorities
When to use each option, what it costs, and what to test.
Module or independent service
- Selection
- Use a service for independent releases or scaling; keep closely coupled transactions in a module.
- Trade-off
- Separate deployment adds network failures, data coordination, and another service to operate.
- Verification
- Review transaction scope, dependency direction, and behavior when a remote service is unavailable.
Shared model or separate read path
- Selection
- Queries need a different data shape from the model used to enforce write rules.
- Trade-off
- A separate read model needs updates and may lag behind writes. CQRS does not require separate databases.
- Verification
- Define acceptable data age and verify projection updates, missing records, and any required rebuild path.
Staged replacement
- Selection
- Existing consumers need continued support while responsibilities move to new components.
- Trade-off
- Smaller cutovers are easier to check, but old and new components must coexist during migration.
- Verification
- Compare consumer-visible behavior and verify write ownership, migration compatibility, and recovery steps.