corpus.blog
Most cited
Talked about
Blogs
41554 blogs · [ { "id": "01a0d9f1-f0ac-72c6-b714-8a87f58d8520", "title": "I Replaced a $120/Year SaaS With My Own App", "url": "https://milanjovanovic.tech/blog/speech-to-text-in-dotnet-with-assemblyai", "published_at": "2026-09-26T00:00:00+00:00" }, { "id": "01a0bb95-0c12-73ef-93b3-b324cf12407c", "title": "Adding an Index Made This Query Slower", "url": "https://milanjovanovic.tech/blog/when-postgres-picks-the-wrong-index", "published_at": "2026-09-19T00:00:00+00:00" }, { "id": "01a09526-933d-7054-a3aa-dc8576d0609a", "title": "Let Postgres Enforce Tenant Isolation", "url": "https://milanjovanovic.tech/blog/postgres-row-level-security-with-ef-core", "published_at": "2026-09-12T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4ca2a40a", "title": "Four Years of Writing Every Week", "url": "https://milanjovanovic.tech/blog/four-years-of-writing-every-week", "published_at": "2026-09-05T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4d7abc7e", "title": "Your ASP.NET Core Endpoints Don't Have a Timeout", "url": "https://milanjovanovic.tech/blog/your-aspnetcore-endpoints-dont-have-a-timeout", "published_at": "2026-08-29T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4dbf262c", "title": "From 17ms to 0.04ms: How to Design the Right SQL Index", "url": "https://milanjovanovic.tech/blog/how-to-design-the-right-sql-index", "published_at": "2026-08-22T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4e8cfd32", "title": "How Do You Build a Social Media Feed? (System Design)", "url": "https://milanjovanovic.tech/blog/how-do-you-build-a-social-media-feed-system-design", "published_at": "2026-08-15T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4ea152e7", "title": "Persisting a Rich Domain Model With EF Core", "url": "https://milanjovanovic.tech/blog/persisting-a-rich-domain-model-with-ef-core", "published_at": "2026-08-08T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4f70bf53", "title": "Should You Split That Into Microservices? Ask These 5 Questions First", "url": "https://milanjovanovic.tech/blog/should-you-split-that-into-microservices-ask-these-5-questions-first", "published_at": "2026-08-01T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f4fbc3067", "title": "The System Design Behind My New SaaS", "url": "https://milanjovanovic.tech/blog/the-system-design-behind-my-new-saas", "published_at": "2026-07-25T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f507b4e98", "title": "How I Migrated My Website to Cloudflare and Saved $228", "url": "https://milanjovanovic.tech/blog/how-i-migrated-my-website-to-cloudflare-and-saved-228-dollars", "published_at": "2026-07-18T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f5084691e", "title": "How to Test Vertical Slice Architecture", "url": "https://milanjovanovic.tech/blog/how-to-test-vertical-slice-architecture", "published_at": "2026-07-11T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f50e88291", "title": "Build Your Own VPN With Tailscale", "url": "https://milanjovanovic.tech/blog/build-your-own-vpn-with-tailscale", "published_at": "2026-07-04T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f516d5b04", "title": "Getting Started With NATS JetStream in .NET", "url": "https://milanjovanovic.tech/blog/getting-started-with-nats-jetstream-in-dotnet", "published_at": "2026-06-27T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f521bd44b", "title": "The Modular Monolith Boundary I Couldn't Take Back", "url": "https://milanjovanovic.tech/blog/the-modular-monolith-boundary-i-couldnt-take-back", "published_at": "2026-06-20T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f526f0d72", "title": "Building Dapr Workflows in .NET With Aspire", "url": "https://milanjovanovic.tech/blog/building-dapr-workflows-in-dotnet-with-aspire", "published_at": "2026-06-13T00:00:00+00:00" }, { "id": "01a087a6-8cf2-7349-bec3-d93f52a5f663", "title": "DRY Is the Most Misunderstood Rule in Programming", "url": "https://milanjovanovic.tech/blog/dry-is-the-most-misunderstood-rule-in-programming", "published_at": "2026-06-06T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe99c1b83b", "title": "Union Types Are Finally Coming to C#", "url": "https://milanjovanovic.tech/blog/union-types-are-finally-coming-to-csharp", "published_at": "2026-05-30T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9a1f0baa", "title": "How to Scale Long-Running API Requests", "url": "https://milanjovanovic.tech/blog/how-to-scale-long-running-api-requests", "published_at": "2026-05-23T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9ab97d01", "title": "When Your Use Case Half-Succeeds: Designing for Partial Failure in .NET", "url": "https://milanjovanovic.tech/blog/when-your-use-case-half-succeeds-designing-for-partial-failure-in-dotnet", "published_at": "2026-05-16T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9ace0e1c", "title": "API Versioning Should Be Your Last Resort", "url": "https://milanjovanovic.tech/blog/api-versioning-should-be-your-last-resort", "published_at": "2026-05-09T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9b10492f", "title": "What Invariants Are (and Why a Domain Model Is the Best Place to Enforce Them)", "url": "https://milanjovanovic.tech/blog/what-invariants-are-and-why-a-domain-model-is-the-best-place-to-enforce-them", "published_at": "2026-05-02T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9b5805a4", "title": "The Test Pyramid Is a Lie (and What I Do Instead)", "url": "https://milanjovanovic.tech/blog/the-test-pyramid-is-a-lie-and-what-i-do-instead", "published_at": "2026-04-25T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9b7335ba", "title": "Why I Switched to Primary Constructors for DI in C#", "url": "https://milanjovanovic.tech/blog/why-i-switched-to-primary-constructors-for-di-in-csharp", "published_at": "2026-04-18T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9c663963", "title": "Implementing the Saga Pattern With Wolverine", "url": "https://milanjovanovic.tech/blog/implementing-the-saga-pattern-with-wolverine", "published_at": "2026-04-11T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9ce46e6d", "title": "Implementing the Inbox Pattern for Reliable Message Consumption", "url": "https://milanjovanovic.tech/blog/implementing-the-inbox-pattern-for-reliable-message-consumption", "published_at": "2026-04-04T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9d740463", "title": "Getting Started With PgVector in .NET for Simple Vector Search", "url": "https://milanjovanovic.tech/blog/getting-started-with-pgvector-in-dotnet-for-simple-vector-search", "published_at": "2026-03-28T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9e1d9e87", "title": "Scaling SignalR With a Redis Backplane", "url": "https://milanjovanovic.tech/blog/scaling-signalr-with-redis-backplane", "published_at": "2026-03-21T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9e53c8e3", "title": "Optimizing Bulk Database Updates in .NET: From Naive to Lightning-Fast", "url": "https://milanjovanovic.tech/blog/optimizing-bulk-database-updates-in-dotnet", "published_at": "2026-03-14T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9e82cc4e", "title": "5 Architecture Tests You Should Add to Your .NET Projects", "url": "https://milanjovanovic.tech/blog/5-architecture-tests-you-should-add-to-your-dotnet-projects", "published_at": "2026-03-07T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9f56630e", "title": "How to Implement Two-Factor Authentication in ASP.NET Core", "url": "https://milanjovanovic.tech/blog/how-to-implement-two-factor-authentication-in-aspnetcore", "published_at": "2026-02-28T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9f8fb017", "title": "Where Vertical Slices Fit Inside the Modular Monolith Architecture", "url": "https://milanjovanovic.tech/blog/where-vertical-slices-fit-inside-the-modular-monolith-architecture", "published_at": "2026-02-21T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfe9ff3a269", "title": "How to Extract Structured Data From Images Using Ollama in .NET", "url": "https://milanjovanovic.tech/blog/how-to-extract-structured-data-from-images-using-ollama-in-dotnet", "published_at": "2026-02-14T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea0cb35b3", "title": "Integrate Keycloak with ASP.NET Core Using OAuth 2.0", "url": "https://milanjovanovic.tech/blog/integrate-keycloak-with-aspnetcore-using-oauth-2", "published_at": "2026-02-07T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea1212ed4", "title": "Containerize Your .NET Applications Without a Dockerfile", "url": "https://milanjovanovic.tech/blog/containerize-your-dotnet-applications-without-a-dockerfile", "published_at": "2026-01-31T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea1e048cc", "title": "A Practical Demo of Zero-Downtime Migrations Using Password Hashing", "url": "https://milanjovanovic.tech/blog/a-practical-demo-of-zero-downtime-migrations-using-password-hashing", "published_at": "2026-01-24T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea26c62d0", "title": "Solving the Distributed Cache Invalidation Problem with Redis and HybridCache", "url": "https://milanjovanovic.tech/blog/solving-the-distributed-cache-invalidation-problem-with-redis-and-hybridcache", "published_at": "2026-01-17T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea2c427e0", "title": "Solving Message Ordering from First Principles", "url": "https://milanjovanovic.tech/blog/solving-message-ordering-from-first-principles", "published_at": "2026-01-10T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea3b25f06", "title": "The Urge to Build Something", "url": "https://milanjovanovic.tech/blog/the-urge-to-build-something", "published_at": "2026-01-03T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea43d1df6", "title": "How to Build a High-Performance Cache Without External Libraries", "url": "https://milanjovanovic.tech/blog/how-to-build-a-high-performance-cache-without-external-libraries", "published_at": "2025-12-27T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea4ffd1ac", "title": "Server-Sent Events in ASP.NET Core and .NET 10", "url": "https://milanjovanovic.tech/blog/server-sent-events-in-aspnetcore-and-dotnet-10", "published_at": "2025-12-20T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea55078a7", "title": "The New .slnx Solution Format (migration guide)", "url": "https://milanjovanovic.tech/blog/the-new-slnx-solution-format-migration-guide", "published_at": "2025-12-13T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea5bdae53", "title": "DbContext is Not Thread-Safe: Parallelizing EF Core Queries the Right Way", "url": "https://milanjovanovic.tech/blog/dbcontext-is-not-thread-safe-parallelizing-ef-core-queries-the-right-way", "published_at": "2025-12-06T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea6553d07", "title": "Vertical Slice Architecture: Where Does the Shared Logic Live?", "url": "https://milanjovanovic.tech/blog/vertical-slice-architecture-where-does-the-shared-logic-live", "published_at": "2025-11-29T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea745ba06", "title": "The False Comfort of the \"Happy Path\": Decoupling Your Services", "url": "https://milanjovanovic.tech/blog/the-false-comfort-of-the-happy-path-decoupling-your-services", "published_at": "2025-11-22T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea82c2d4e", "title": "Exploring C# File-based Apps in .NET 10", "url": "https://milanjovanovic.tech/blog/exploring-csharp-file-based-apps-in-dotnet-10", "published_at": "2025-11-15T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea859cdee", "title": "The Idempotent Consumer Pattern in .NET (And Why You Need It)", "url": "https://milanjovanovic.tech/blog/the-idempotent-consumer-pattern-in-dotnet-and-why-you-need-it", "published_at": "2025-11-08T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea931a720", "title": "What's New in EF Core 10: LeftJoin and RightJoin Operators in LINQ", "url": "https://milanjovanovic.tech/blog/whats-new-in-ef-core-10-leftjoin-and-rightjoin-operators-in-linq", "published_at": "2025-11-01T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfea99e5870", "title": "The Interview Question That Changed How I Think About System Design", "url": "https://milanjovanovic.tech/blog/the-interview-question-that-changed-how-i-think-about-system-design", "published_at": "2025-10-25T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaa6abd46", "title": "6 Steps for Setting Up a New .NET Project the Right Way", "url": "https://milanjovanovic.tech/blog/6-steps-for-setting-up-a-new-dotnet-project-the-right-way", "published_at": "2025-10-18T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaa771643", "title": "Building Fast Serverless APIs With Minimal APIs on AWS Lambda", "url": "https://milanjovanovic.tech/blog/building-fast-serverless-apis-with-minimal-apis-on-aws-lambda", "published_at": "2025-10-11T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaa986e06", "title": "Using Stored Procedures and Functions With EF Core and PostgreSQL", "url": "https://milanjovanovic.tech/blog/using-stored-procedures-and-functions-with-ef-core-and-postgresql", "published_at": "2025-10-04T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeab0caa18", "title": "Building Secure APIs with Role-Based Access Control in ASP.NET Core", "url": "https://milanjovanovic.tech/blog/building-secure-apis-with-role-based-access-control-in-aspnetcore", "published_at": "2025-09-27T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeab635fb3", "title": "Distributed Locking in .NET: Coordinating Work Across Multiple Instances", "url": "https://milanjovanovic.tech/blog/distributed-locking-in-dotnet-coordinating-work-across-multiple-instances", "published_at": "2025-09-20T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeabe9bbe5", "title": "Vertical Slice Architecture Is Easier Than You Think", "url": "https://milanjovanovic.tech/blog/vertical-slice-architecture-is-easier-than-you-think", "published_at": "2025-09-13T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeac6e8040", "title": "Building Semantic Search with Amazon S3 Vectors and Semantic Kernel", "url": "https://milanjovanovic.tech/blog/building-semantic-search-with-amazon-s3-vectors-and-semantic-kernel", "published_at": "2025-09-06T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeacaa7dea", "title": "Standalone Aspire Dashboard Setup for Distributed .NET Applications", "url": "https://milanjovanovic.tech/blog/standalone-aspire-dashboard-setup-for-distributed-dotnet-applications", "published_at": "2025-08-30T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeace28db6", "title": "The Real Cost of Abstractions in .NET", "url": "https://milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet", "published_at": "2025-08-23T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeada1a352", "title": "Building Generative AI Applications With GitHub Models and .NET Aspire", "url": "https://milanjovanovic.tech/blog/building-generative-ai-applications-with-github-models-and-dotnet-aspire", "published_at": "2025-08-16T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeada61dd0", "title": "The 5 Most Common REST API Design Mistakes (and How to Avoid Them)", "url": "https://milanjovanovic.tech/blog/the-5-most-common-rest-api-design-mistakes-and-how-to-avoid-them", "published_at": "2025-08-09T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeadcafe2c", "title": "How to Keep Your Data Boundaries Intact in a Modular Monolith", "url": "https://milanjovanovic.tech/blog/how-to-keep-your-data-boundaries-intact-in-a-modular-monolith", "published_at": "2025-08-02T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeae0523b4", "title": "Named Query Filters in EF 10 (multiple query filters per entity)", "url": "https://milanjovanovic.tech/blog/named-query-filters-in-ef-10-multiple-query-filters-per-entity", "published_at": "2025-07-26T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaeac368c", "title": "PDF Reporting in .NET With HTML Templates and PuppeteerSharp (and it's free)", "url": "https://milanjovanovic.tech/blog/pdf-reporting-in-dotnet-with-html-templates-and-puppeteersharp", "published_at": "2025-07-19T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaee6236d", "title": "Global Error Handling in ASP.NET Core: From Middleware to Modern Handlers", "url": "https://milanjovanovic.tech/blog/global-error-handling-in-aspnetcore-from-middleware-to-modern-handlers", "published_at": "2025-07-12T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeaf4845f7", "title": "Using .NET Aspire With the Docker Publisher", "url": "https://milanjovanovic.tech/blog/using-dotnet-aspire-with-the-docker-publisher", "published_at": "2025-07-05T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeafa51586", "title": "Testcontainers Best Practices for .NET Integration Testing", "url": "https://milanjovanovic.tech/blog/testcontainers-best-practices-dotnet-integration-testing", "published_at": "2025-06-28T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeafe5f5ce", "title": "Monitoring .NET Applications with OpenTelemetry and Grafana", "url": "https://milanjovanovic.tech/blog/monitoring-dotnet-applications-with-opentelemetry-and-grafana", "published_at": "2025-06-21T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb03ceb4d", "title": "Run C# Scripts With dotnet run app.cs (No Project Files Needed)", "url": "https://milanjovanovic.tech/blog/run-csharp-scripts-with-dotnet-run-app-no-project-files-needed", "published_at": "2025-06-14T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb0af2320", "title": "Debunking the \"Filter Early, JOIN Later\" SQL Performance Myth", "url": "https://milanjovanovic.tech/blog/debunking-the-filter-early-join-later-sql-performance-myth", "published_at": "2025-06-07T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb0d652f6", "title": "YARP vs Nginx - A Quick Performance Comparison", "url": "https://milanjovanovic.tech/blog/yarp-vs-nginx-a-quick-performance-comparison", "published_at": "2025-05-31T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb1514f2d", "title": "Building a Custom Domain Events Dispatcher in .NET", "url": "https://milanjovanovic.tech/blog/building-a-custom-domain-events-dispatcher-in-dotnet", "published_at": "2025-05-24T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb201c7d1", "title": "CQRS Pattern the Way It Should've Been From the Start", "url": "https://milanjovanovic.tech/blog/cqrs-pattern-the-way-it-should-have-been-from-the-start", "published_at": "2025-05-17T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb2e41c60", "title": "From Anemic Models to Behavior-Driven Models: A Practical DDD Refactor in C#", "url": "https://milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp", "published_at": "2025-05-10T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb37a4d92", "title": "Event-Driven Architecture in .NET with RabbitMQ", "url": "https://milanjovanovic.tech/blog/event-driven-architecture-in-dotnet-with-rabbitmq", "published_at": "2025-05-03T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb3861e5f", "title": "Refactoring Overgrown Bounded Contexts in Modular Monoliths", "url": "https://milanjovanovic.tech/blog/refactoring-overgrown-bounded-contexts-in-modular-monoliths", "published_at": "2025-04-26T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb436a8ea", "title": "Understanding Microservices: Core Concepts and Benefits", "url": "https://milanjovanovic.tech/blog/understanding-microservices-core-concepts-and-benefits", "published_at": "2025-04-19T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb526802c", "title": "What is Vector Search? A Concise Guide", "url": "https://milanjovanovic.tech/blog/what-is-vector-search-a-concise-guide", "published_at": "2025-04-12T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb544138d", "title": "MediatR and MassTransit Going Commercial: What This Means For You", "url": "https://milanjovanovic.tech/blog/mediatr-and-masstransit-going-commercial-what-this-means-for-you", "published_at": "2025-04-05T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb5c71b9b", "title": "How .NET Aspire Simplifies Service Discovery", "url": "https://milanjovanovic.tech/blog/how-dotnet-aspire-simplifies-service-discovery", "published_at": "2025-03-29T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb667d33e", "title": "Options Pattern Validation in ASP.NET Core With FluentValidation", "url": "https://milanjovanovic.tech/blog/options-pattern-validation-in-aspnetcore-with-fluentvalidation", "published_at": "2025-03-22T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb6d6bf77", "title": "Streamlining .NET 9 Deployment With GitHub Actions and Azure", "url": "https://milanjovanovic.tech/blog/streamlining-dotnet-9-deployment-with-github-actions-and-azure", "published_at": "2025-03-15T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb7a14c56", "title": "Better Request Tracing with User Context in ASP.NET Core", "url": "https://milanjovanovic.tech/blog/better-request-tracing-with-user-context-in-asp-net-core", "published_at": "2025-03-08T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb87ca0d1", "title": "Introduction to Dapr for .NET Developers", "url": "https://milanjovanovic.tech/blog/introduction-to-dapr-for-dotnet-developers", "published_at": "2025-03-01T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeb9554e5b", "title": "Building a Better MediatR Publisher With Channels (and why you shouldn't)", "url": "https://milanjovanovic.tech/blog/building-a-better-mediatr-publisher-with-channels-and-why-you-shouldnt", "published_at": "2025-02-22T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeba35220d", "title": "Understanding Cursor Pagination and Why It's So Fast (Deep Dive)", "url": "https://milanjovanovic.tech/blog/understanding-cursor-pagination-and-why-its-so-fast-deep-dive", "published_at": "2025-02-15T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfeba6084bf", "title": "Stop Conflating CQRS and MediatR", "url": "https://milanjovanovic.tech/blog/stop-conflating-cqrs-and-mediatr", "published_at": "2025-02-08T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebaa12dae", "title": "Overriding Default HTTP Resilience Handlers in .NET", "url": "https://milanjovanovic.tech/blog/overriding-default-http-resilience-handlers-in-dotnet", "published_at": "2025-02-01T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebaf2ba20", "title": "Implementing AES Encryption With C#", "url": "https://milanjovanovic.tech/blog/implementing-aes-encryption-with-csharp", "published_at": "2025-01-25T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebbe4baa0", "title": "Scaling Monoliths: A Practical Guide for Growing Systems", "url": "https://milanjovanovic.tech/blog/scaling-monoliths-a-practical-guide-for-growing-systems", "published_at": "2025-01-18T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebc906c9d", "title": "Working with LLMs in .NET using Microsoft.Extensions.AI", "url": "https://milanjovanovic.tech/blog/working-with-llms-in-dotnet-using-microsoft-extensions-ai", "published_at": "2025-01-11T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebd8b8a40", "title": "Unit Testing Clean Architecture Use Cases", "url": "https://milanjovanovic.tech/blog/unit-testing-clean-architecture-use-cases", "published_at": "2025-01-04T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebdca93b2", "title": "What Rewriting a 40-Year-Old Project Taught Me About Software Development", "url": "https://milanjovanovic.tech/blog/what-rewriting-a-40-year-old-project-taught-me-about-software-development", "published_at": "2024-12-28T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebec2a962", "title": "Scheduling Background Jobs With Quartz in .NET (advanced concepts)", "url": "https://milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts", "published_at": "2024-12-21T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebf937b21", "title": "Internal vs. Public APIs in Modular Monoliths", "url": "https://milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths", "published_at": "2024-12-14T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebf9cd5fb", "title": "Central Package Management in .NET - Simplify NuGet Dependencies", "url": "https://milanjovanovic.tech/blog/central-package-management-in-net-simplify-nuget-dependencies", "published_at": "2024-12-07T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfebfcd7d77", "title": "Implementing the Saga Pattern With MassTransit", "url": "https://milanjovanovic.tech/blog/implementing-the-saga-pattern-with-masstransit", "published_at": "2024-11-30T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfec05938f9", "title": "Building Async APIs in ASP.NET Core - The Right Way", "url": "https://milanjovanovic.tech/blog/building-async-apis-in-aspnetcore-the-right-way", "published_at": "2024-11-23T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfec0f3c598", "title": "HybridCache in ASP.NET Core - New Caching Library", "url": "https://milanjovanovic.tech/blog/hybrid-cache-in-aspnetcore-new-caching-library", "published_at": "2024-11-16T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfec138a0d8", "title": "Functional Programming in C#: The Practical Parts", "url": "https://milanjovanovic.tech/blog/functional-programming-in-csharp-the-practical-parts", "published_at": "2024-11-09T00:00:00+00:00" }, { "id": "01a087a6-8cf3-703e-8b0e-2cfec2219afd", "title": "Clean Architecture: The Missing Chapter", "url": "https://milanjovanovic.tech/blog/clean-architecture-the-missing-chapter", "published_at": "2024-11-02T00:00:00+00:00" } ] posts
Claim your blog
Back to milanjovanovic.tech
Blog · corpus.blog/blogs/milanjovanovic.tech/posts
milanjovanovic.tech
milanjovanovic.tech
2026
I Replaced a $120/Year SaaS With My Own App
original ↗
26 Sept 2026
Adding an Index Made This Query Slower
original ↗
19 Sept 2026
Let Postgres Enforce Tenant Isolation
original ↗
12 Sept 2026
Four Years of Writing Every Week
original ↗
5 Sept 2026
Your ASP.NET Core Endpoints Don't Have a Timeout
original ↗
29 Aug 2026
From 17ms to 0.04ms: How to Design the Right SQL Index
original ↗
22 Aug 2026
How Do You Build a Social Media Feed? (System Design)
original ↗
15 Aug 2026
Persisting a Rich Domain Model With EF Core
original ↗
8 Aug 2026
Should You Split That Into Microservices? Ask These 5 Questions First
original ↗
1 Aug 2026
The System Design Behind My New SaaS
original ↗
25 Jul 2026
How I Migrated My Website to Cloudflare and Saved $228
original ↗
18 Jul 2026
How to Test Vertical Slice Architecture
original ↗
11 Jul 2026
Build Your Own VPN With Tailscale
original ↗
4 Jul 2026
Getting Started With NATS JetStream in .NET
original ↗
27 Jun 2026
The Modular Monolith Boundary I Couldn't Take Back
original ↗
20 Jun 2026
Building Dapr Workflows in .NET With Aspire
original ↗
13 Jun 2026
DRY Is the Most Misunderstood Rule in Programming
original ↗
6 Jun 2026
Union Types Are Finally Coming to C#
original ↗
30 May 2026
How to Scale Long-Running API Requests
original ↗
23 May 2026
When Your Use Case Half-Succeeds: Designing for Partial Failure in .NET
original ↗
16 May 2026
API Versioning Should Be Your Last Resort
original ↗
9 May 2026
What Invariants Are (and Why a Domain Model Is the Best Place to Enforce Them)
original ↗
2 May 2026
The Test Pyramid Is a Lie (and What I Do Instead)
original ↗
25 Apr 2026
Why I Switched to Primary Constructors for DI in C#
original ↗
18 Apr 2026
Implementing the Saga Pattern With Wolverine
original ↗
11 Apr 2026
Implementing the Inbox Pattern for Reliable Message Consumption
original ↗
4 Apr 2026
Getting Started With PgVector in .NET for Simple Vector Search
original ↗
28 Mar 2026
Scaling SignalR With a Redis Backplane
original ↗
21 Mar 2026
Optimizing Bulk Database Updates in .NET: From Naive to Lightning-Fast
original ↗
14 Mar 2026
5 Architecture Tests You Should Add to Your .NET Projects
original ↗
7 Mar 2026
How to Implement Two-Factor Authentication in ASP.NET Core
original ↗
28 Feb 2026
Where Vertical Slices Fit Inside the Modular Monolith Architecture
original ↗
21 Feb 2026
How to Extract Structured Data From Images Using Ollama in .NET
original ↗
14 Feb 2026
Integrate Keycloak with ASP.NET Core Using OAuth 2.0
original ↗
7 Feb 2026
Containerize Your .NET Applications Without a Dockerfile
original ↗
31 Jan 2026
A Practical Demo of Zero-Downtime Migrations Using Password Hashing
original ↗
24 Jan 2026
Solving the Distributed Cache Invalidation Problem with Redis and HybridCache
original ↗
17 Jan 2026
Solving Message Ordering from First Principles
original ↗
10 Jan 2026
The Urge to Build Something
original ↗
3 Jan 2026
2025
How to Build a High-Performance Cache Without External Libraries
original ↗
27 Dec 2025
Server-Sent Events in ASP.NET Core and .NET 10
original ↗
20 Dec 2025
The New .slnx Solution Format (migration guide)
original ↗
13 Dec 2025
DbContext is Not Thread-Safe: Parallelizing EF Core Queries the Right Way
original ↗
6 Dec 2025
Vertical Slice Architecture: Where Does the Shared Logic Live?
original ↗
29 Nov 2025
The False Comfort of the "Happy Path": Decoupling Your Services
original ↗
22 Nov 2025
Exploring C# File-based Apps in .NET 10
original ↗
15 Nov 2025
The Idempotent Consumer Pattern in .NET (And Why You Need It)
original ↗
8 Nov 2025
What's New in EF Core 10: LeftJoin and RightJoin Operators in LINQ
original ↗
1 Nov 2025
The Interview Question That Changed How I Think About System Design
original ↗
25 Oct 2025
6 Steps for Setting Up a New .NET Project the Right Way
original ↗
18 Oct 2025
Building Fast Serverless APIs With Minimal APIs on AWS Lambda
original ↗
11 Oct 2025
Using Stored Procedures and Functions With EF Core and PostgreSQL
original ↗
4 Oct 2025
Building Secure APIs with Role-Based Access Control in ASP.NET Core
original ↗
27 Sept 2025
Distributed Locking in .NET: Coordinating Work Across Multiple Instances
original ↗
20 Sept 2025
Vertical Slice Architecture Is Easier Than You Think
original ↗
13 Sept 2025
Building Semantic Search with Amazon S3 Vectors and Semantic Kernel
original ↗
6 Sept 2025
Standalone Aspire Dashboard Setup for Distributed .NET Applications
original ↗
30 Aug 2025
The Real Cost of Abstractions in .NET
original ↗
23 Aug 2025
Building Generative AI Applications With GitHub Models and .NET Aspire
original ↗
16 Aug 2025
The 5 Most Common REST API Design Mistakes (and How to Avoid Them)
original ↗
9 Aug 2025
How to Keep Your Data Boundaries Intact in a Modular Monolith
original ↗
2 Aug 2025
Named Query Filters in EF 10 (multiple query filters per entity)
original ↗
26 Jul 2025
PDF Reporting in .NET With HTML Templates and PuppeteerSharp (and it's free)
original ↗
19 Jul 2025
Global Error Handling in ASP.NET Core: From Middleware to Modern Handlers
original ↗
12 Jul 2025
Using .NET Aspire With the Docker Publisher
original ↗
5 Jul 2025
Testcontainers Best Practices for .NET Integration Testing
original ↗
28 Jun 2025
Monitoring .NET Applications with OpenTelemetry and Grafana
original ↗
21 Jun 2025
Run C# Scripts With dotnet run app.cs (No Project Files Needed)
original ↗
14 Jun 2025
Debunking the "Filter Early, JOIN Later" SQL Performance Myth
original ↗
7 Jun 2025
YARP vs Nginx - A Quick Performance Comparison
original ↗
31 May 2025
Building a Custom Domain Events Dispatcher in .NET
original ↗
24 May 2025
CQRS Pattern the Way It Should've Been From the Start
original ↗
17 May 2025
From Anemic Models to Behavior-Driven Models: A Practical DDD Refactor in C#
original ↗
10 May 2025
Event-Driven Architecture in .NET with RabbitMQ
original ↗
3 May 2025
Refactoring Overgrown Bounded Contexts in Modular Monoliths
original ↗
26 Apr 2025
Understanding Microservices: Core Concepts and Benefits
original ↗
19 Apr 2025
What is Vector Search? A Concise Guide
original ↗
12 Apr 2025
MediatR and MassTransit Going Commercial: What This Means For You
original ↗
5 Apr 2025
How .NET Aspire Simplifies Service Discovery
original ↗
29 Mar 2025
Options Pattern Validation in ASP.NET Core With FluentValidation
original ↗
22 Mar 2025
Streamlining .NET 9 Deployment With GitHub Actions and Azure
original ↗
15 Mar 2025
Better Request Tracing with User Context in ASP.NET Core
original ↗
8 Mar 2025
Introduction to Dapr for .NET Developers
original ↗
1 Mar 2025
Building a Better MediatR Publisher With Channels (and why you shouldn't)
original ↗
22 Feb 2025
Understanding Cursor Pagination and Why It's So Fast (Deep Dive)
original ↗
15 Feb 2025
Stop Conflating CQRS and MediatR
original ↗
8 Feb 2025
Overriding Default HTTP Resilience Handlers in .NET
original ↗
1 Feb 2025
Implementing AES Encryption With C#
original ↗
25 Jan 2025
Scaling Monoliths: A Practical Guide for Growing Systems
original ↗
18 Jan 2025
Working with LLMs in .NET using Microsoft.Extensions.AI
original ↗
11 Jan 2025
Unit Testing Clean Architecture Use Cases
original ↗
4 Jan 2025
2024
What Rewriting a 40-Year-Old Project Taught Me About Software Development
original ↗
28 Dec 2024
Scheduling Background Jobs With Quartz in .NET (advanced concepts)
original ↗
21 Dec 2024
Internal vs. Public APIs in Modular Monoliths
original ↗
14 Dec 2024
Central Package Management in .NET - Simplify NuGet Dependencies
original ↗
7 Dec 2024
Implementing the Saga Pattern With MassTransit
original ↗
30 Nov 2024
Building Async APIs in ASP.NET Core - The Right Way
original ↗
23 Nov 2024
HybridCache in ASP.NET Core - New Caching Library
original ↗
16 Nov 2024
Functional Programming in C#: The Practical Parts
original ↗
9 Nov 2024
Clean Architecture: The Missing Chapter
original ↗
2 Nov 2024
Next