var moritz = new Engineer
{
Name = "Moritz Waldau",
Role = "IT Consultant · .NET & Azure",
Location = "Hannover, Germany",
Degree = "B.Sc. Business Information Systems (dual study program)",
Focus = [".NET", "Azure", "Clean Architecture", "AI Agents"],
Currently = "Owning the architecture of a .NET 4.8 → .NET 9 MAUI modernization",
Track = "Applications used daily by 13,000+ financial advisors",
Daily = ["Claude Code", "GitHub Copilot", "own MCP servers"],
OffDuty = ["Hiking in summer", "Skiing in winter"],
};I design and modernize .NET systems that people depend on every day — and I spend a growing share of my time on where AI agents fit into that work: building agents, writing MCP servers, and using agentic tooling as a first-class part of the development loop rather than an add-on.
| Backend | Cloud & DevOps | Data | Frontend |
|---|---|---|---|
|
|
|
|
|
|
A reference architecture for modern e-commerce systems: eight microservices on .NET 10,
cut along Clean Architecture and DDD boundaries, CQRS over MediatR, and a
|
My personal site — a Blazor WebAssembly PWA on .NET 10 with a service worker for offline use, built and deployed to GitHub Pages through GitHub Actions. Also on GitHub: EmployeeManagementSystem — a cloud-native .NET 9 app with Aspire, Docker and GitHub Actions on Azure Container Apps (on my second account @MoritzWaldau). |
flowchart LR
UI[Blazor WASM<br/>MudBlazor] --> GW[YARP Gateway + BFF<br/>Auth0 OIDC]
GW --> CAT[Catalog]
GW --> BAS[Basket]
GW --> ORD[Ordering]
GW --> PAY[Payment]
GW --> USR[UserProfile]
GW --> ADV[Advisory<br/>Azure OpenAI + MCP]
CAT --> DB[(PostgreSQL<br/>one per service)]
ORD --> DB
PAY --> DB
CAT --> RD[(Redis<br/>HybridCache)]
BAS --> RD
ORD -->|Outbox| SB{{Azure Service Bus}}
SB -->|Inbox| NOT[Notification]
SB --> WHK[Webhooks]
How a request flows through it — click to expand
- The Blazor WASM client never talks to a service directly — every call goes through the YARP gateway, which acts as a BFF and keeps the Auth0 OIDC session in a cookie, so no tokens live in the browser.
- Each service owns its domain, its application layer (CQRS handlers over MediatR) and its own PostgreSQL schema. No shared database, no cross-service joins.
- State changes other services care about are written to an Outbox table in the same transaction as the domain change, then relayed to Azure Service Bus. Consumers dedupe through an Inbox, so delivery is at-least-once but processing is effectively once.
- Hot read paths (catalog, basket) sit behind Redis HybridCache — L1 in-process, L2 distributed, invalidated by the same events.
- The Advisory service exposes the catalog to an Azure OpenAI agent through a custom MCP server, so the agent works against the same bounded context as the rest of the system.


