A customer taps "Pay" in the mobile app. Here's every hop, and the concept that applies at each one.
.NET 10 Reference .NET 10 stack, hop by hop
| Hop | Library / API | What it does here |
| 1. Client sign-in | Microsoft.Identity.Client (MSAL.NET) in the .NET MAUI app | OAuth 2.0 / OIDC with PKCE; gets an access token for the payments API |
| 2. Edge | Azure Front Door + WAF (config); built-in MapStaticAssets | TLS, WAF rules, CDN caching of static files |
| 3. Gateway | Azure API Management, or Yarp.ReverseProxy in .NET; built-in Microsoft.AspNetCore.RateLimiting | Routing, JWT check, quotas and rate limits |
| 4. Service | built-in ASP.NET Core minimal APIs, Microsoft.Identity.Web, AddValidation(), AddProblemDetails() | Stateless API: validate token and input, return RFC 9457 errors |
| 5. Outbound calls | Microsoft.Extensions.Http.Resilience | Timeouts, retries, circuit breakers to fraud and core systems |
| 6. Cache | Microsoft.Extensions.Caching.Hybrid + Microsoft.Extensions.Caching.StackExchangeRedis | L1 + Redis L2 for reference data and balances |
| 7. Database | Microsoft.EntityFrameworkCore.SqlServer (EF Core 10) | ACID transaction; unique index on the idempotency key; outbox row in the same transaction |
| 8. Messaging | Azure.Messaging.ServiceBus; outbox via WolverineFx (free) or MassTransit v9 commercial licence | Publish PaymentCompleted to notifications, ledger, analytics |
| 9. AI | Microsoft.Extensions.AI, Microsoft.Extensions.VectorData.Abstractions, Microsoft.Agents.AI | Fraud explanation, RAG help, agent actions with approvals |
| 10. Observability | OpenTelemetry.Extensions.Hosting, Azure.Monitor.OpenTelemetry.AspNetCore; Aspire ServiceDefaults + dashboard | One trace ID from tap to ledger; metrics for SLOs |
app.MapPost("/payments", async (PaymentRequest req, [FromHeader(Name = "Idempotency-Key")] Guid key,
PaymentsDb db, CancellationToken ct) =>
{
if (await db.Payments.AnyAsync(p => p.IdempotencyKey == key, ct))
return Results.Ok(); // retry: same result, no double charge
var payment = Payment.Create(req, key);
db.Payments.Add(payment);
db.Outbox.Add(OutboxMessage.From(new PaymentCompleted(payment.Id))); // same transaction
await db.SaveChangesAsync(ct); // unique index backs up the check
return Results.Created($"/payments/{payment.Id}", payment.Id);
})
.RequireAuthorization("payments.write")
.RequireRateLimiting("per-user");
What happens when you tap "Pay" in a banking app? 💳 (a system design tour)
DNS → WAF/CDN → API gateway (JWT, rate limit) → load balancer → stateless service → cache + DB (ACID + idempotency key) → outbox → event bus → notifications, ledger, analytics.
Every arrow is a design decision: sync or async, consistency or availability, retry or fail fast.
Save this for your next system design interview. #SystemDesign #Architecture #Banking