<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Software Architecture That Survives on Atharva Pandey</title><link>https://atharva.page/series/software-architecture-that-survives/</link><description>Recent content in Software Architecture That Survives on Atharva Pandey</description><generator>Hugo</generator><language>en-us</language><copyright>Copyright ©</copyright><lastBuildDate>Fri, 23 Aug 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://atharva.page/series/software-architecture-that-survives/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 8: Technical Debt — When to pay, when to live with it</title><link>https://atharva.page/post/fundamentals/arch-tech-debt/</link><pubDate>Fri, 23 Aug 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-tech-debt/</guid><description>&lt;p&gt;The term &amp;ldquo;technical debt&amp;rdquo; gets used to mean everything from &amp;ldquo;this code is a mess&amp;rdquo; to &amp;ldquo;we made a pragmatic shortcut we need to revisit&amp;rdquo; to &amp;ldquo;this system has grown organically and nobody understands it anymore.&amp;rdquo; These are different problems requiring different responses. Treating all technical debt as something that must be paid now, or all of it as something acceptable to defer indefinitely — both lead to bad outcomes. The skill is knowing which debt to address, when, and how.&lt;/p&gt;</description></item><item><title>Lesson 7: Migration Strategies — Strangler fig and feature flags</title><link>https://atharva.page/post/fundamentals/arch-migrations/</link><pubDate>Wed, 07 Aug 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-migrations/</guid><description>&lt;p&gt;Rewrites are seductive. The existing system is messy, it&amp;rsquo;s slow to change, and the new system in your head is clean and fast and well-designed. Then you start the rewrite. Six months in, you&amp;rsquo;ve rebuilt 40% of the functionality and the remaining 60% is more complex than you thought. Meanwhile, the old system keeps shipping features. The new system falls behind, gets cancelled, and you&amp;rsquo;re back where you started, except now you&amp;rsquo;ve lost six months and the team is demoralized. I&amp;rsquo;ve seen this happen twice. The third time, we used the strangler fig pattern instead, and it worked.&lt;/p&gt;</description></item><item><title>Lesson 6: API Versioning — URL, header, or content negotiation</title><link>https://atharva.page/post/fundamentals/arch-api-versioning/</link><pubDate>Wed, 24 Jul 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-api-versioning/</guid><description>&lt;p&gt;The first time I shipped a breaking change to a production API without a version, I got an incident at 2am because a partner integration stopped working. They&amp;rsquo;d been calling &lt;code&gt;/api/orders&lt;/code&gt; for six months. I changed the response shape. Their code broke. That was when &amp;ldquo;API versioning&amp;rdquo; moved from &amp;ldquo;thing to do eventually&amp;rdquo; to &amp;ldquo;thing to do before you ship anything external.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s no universally right answer to how you version APIs. There are tradeoffs, and the choice you make will shape your codebase for years. Here&amp;rsquo;s how I think about it.&lt;/p&gt;</description></item><item><title>Lesson 5: DDD Essentials — Bounded contexts and aggregates</title><link>https://atharva.page/post/fundamentals/arch-ddd/</link><pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-ddd/</guid><description>&lt;p&gt;The concept of &amp;ldquo;customer&amp;rdquo; meant something different in every team I talked to at one company. To the billing team, a customer was a billing account. To the support team, a customer was a person who filed tickets. To the identity team, a customer was an authenticated principal. Every team had their own &lt;code&gt;Customer&lt;/code&gt; struct, and syncing them was a full-time job. That&amp;rsquo;s the problem DDD&amp;rsquo;s bounded context concept solves — and it&amp;rsquo;s one of those ideas that sounds academic until you&amp;rsquo;ve suffered without it.&lt;/p&gt;</description></item><item><title>Lesson 4: CQRS — When reads and writes need different models</title><link>https://atharva.page/post/fundamentals/arch-cqrs/</link><pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-cqrs/</guid><description>&lt;p&gt;I maintained an e-commerce admin dashboard that had a query so complex it took 12 seconds to run. It joined seven tables across the orders, inventory, and customers domains to build a summary view of &amp;ldquo;all orders pending fulfillment, with customer tier, item details, and warehouse stock levels.&amp;rdquo; Every time the admin loaded the page, twelve seconds. We tried indexes, caching, materialized views — all helped at the margins. The fundamental problem was that we were asking our write-optimized relational model to answer a read-optimized reporting question. Separating the read model was the only real fix.&lt;/p&gt;</description></item><item><title>Lesson 3: Event-Driven Architecture — Events vs commands</title><link>https://atharva.page/post/fundamentals/arch-event-driven/</link><pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-event-driven/</guid><description>&lt;p&gt;I used to use &amp;ldquo;event&amp;rdquo; and &amp;ldquo;command&amp;rdquo; interchangeably. A message is a message, right? Then I started debugging an event-driven system where the payment service was publishing &lt;code&gt;ProcessPayment&lt;/code&gt; events, the order service was publishing &lt;code&gt;CreateShipment&lt;/code&gt; events, and two teams were arguing about who owned the workflow. The problem was naming: they were publishing commands disguised as events. The distinction isn&amp;rsquo;t pedantic — it determines who owns the workflow and how the system evolves.&lt;/p&gt;</description></item><item><title>Lesson 2: Clean Architecture — Not the textbook version</title><link>https://atharva.page/post/fundamentals/arch-clean/</link><pubDate>Sun, 19 May 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-clean/</guid><description>&lt;p&gt;I&amp;rsquo;ve read the Clean Architecture book. I&amp;rsquo;ve also seen teams implement it so literally that they had six layers of indirection for a CRUD endpoint: a controller called a use case, which called a domain service, which called a port, which went through an adapter, which called a repository, which hit the database. Each hop had its own error mapping. Changing a database column required touching eight files. That&amp;rsquo;s not clean. That&amp;rsquo;s engineering theater.&lt;/p&gt;</description></item><item><title>Lesson 1: Monolith First — Starting with microservices is usually wrong</title><link>https://atharva.page/post/fundamentals/arch-monolith-first/</link><pubDate>Fri, 03 May 2024 00:00:00 +0000</pubDate><guid>https://atharva.page/post/fundamentals/arch-monolith-first/</guid><description>&lt;p&gt;I&amp;rsquo;ve seen two teams start new products with microservices. One spent four months before they had anything deployed — Kubernetes setup, service discovery, distributed tracing, a CI/CD pipeline for twelve repos, and debates about how to split domains they hadn&amp;rsquo;t fully understood yet. They ran out of runway. The other team I worked on started with a monolith, shipped their first real user feature in three weeks, and only extracted services when the actual pain of growth made the benefit obvious. We&amp;rsquo;re still running that system, and it handles tens of millions of requests a day.&lt;/p&gt;</description></item></channel></rss>