← All projects
API Architecture Demo: Bad Design vs. Good Design
C#ASP.NET CoreEF CoreDapperSQL Serverk6Next.js
A live architecture write-up, not just a slide deck claim: erik-mostert-profile-bad-api deliberately implements common anti-patterns (Singleton DbContext, N+1 queries, no pagination, no caching, no rate limiting) against a seeded e-commerce database, while erik-mostert-profile-good-api solves the same problem with a layered, test-first architecture (Dapper read repositories, output caching, a transactional outbox feeding a denormalized read model, per-IP rate limiting). Both repos are fully self-contained and independently clonable — no shared code between them — and both run the identical k6 load profile so the comparison numbers are apples to apples, not two separate stories.
- Verified, reproducible failure mode: the bad API's unpaginated orders endpoint took ~230s to stream ~6.7MB before the SQL client itself threw a connection timeout.
- The good API's read path is backed by a genuine outbox-driven read model with its own separate EF Core migration history, proven end to end by an integration test running against a real SQL Server container.
- Identical k6 ramping-VU load profile (0 → 50 → 200 → 500) against both APIs, so the comparison charts reflect the same offered load, not a favorable mismatch.