<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Fredrick Oladipupo</title>
    <description>The latest articles on Forem by Fredrick Oladipupo (@fredrick_oladipupo).</description>
    <link>https://forem.com/fredrick_oladipupo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2940427%2F92331d7f-d347-4a1c-b9f0-ecc82badcfeb.jpg</url>
      <title>Forem: Fredrick Oladipupo</title>
      <link>https://forem.com/fredrick_oladipupo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fredrick_oladipupo"/>
    <language>en</language>
    <item>
      <title>I couldn’t come up with a title</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Thu, 31 Jul 2025 09:59:14 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/i-couldnt-come-up-with-a-title-1887</link>
      <guid>https://forem.com/fredrick_oladipupo/i-couldnt-come-up-with-a-title-1887</guid>
      <description>&lt;p&gt;&lt;strong&gt;PS: This would skew more towards finding peace than loading up on aspiration/goals, and that’s a reflection of where I am in life. That may/may not apply to you, depending on where you are in your own journey.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Most of what you see in life is a reflection of your own life&lt;/strong&gt;. A simple thing like your neighbourhood can shape your whole perception of the world. But the truth is, that is not the world; that is just your world. The world is so much bigger than your little town or what the Twitter algorithm feeds you. That means 👇&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You live in a bubble&lt;/strong&gt;. It is important to know this. For everything you know, there are a million things you don’t. For every feed you see on your social media, there is a billion you don’t know about. Your music playlist is a bubble. Your YouTube feed is a bubble. Your ideology is a bubble. The number of things you don’t know is so massive that there is no reason for you not to be humble. But that's okay because 👇&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Most things don’t matter;&lt;/strong&gt; they seem like they are, but they are not. Stay grounded in things that truly matter. Unfortunately, I'm unable to disclose what those are. That's the irony of life. In the end, when the ocean rises, we have to paddle our canoes; no one is going to do that for us. That is why it is important you 👇&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t major in minor things&lt;/strong&gt;. A lot of things are important, but few are important to you. Even fewer should be important to you. Stay on those. Dedicate yourself to those. &lt;br&gt;
&lt;strong&gt;Minor time&lt;/strong&gt;: Talking about doing it, writing about doing it, telling people about doing it, presenting how you are going to do it, researching about it, thinking about doing it. &lt;br&gt;
&lt;strong&gt;Major time&lt;/strong&gt;: Doing it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Action is the bottleneck.&lt;/strong&gt; When attempting a big goal, People often assume what they need is more information, more research, more talks, more thoughts, a new course, more bookmarked YouTube video links. Information is not the problem anymore. Almost everything you would want to know is on the internet. Most universities have open courses available on their website. Action is the new gold. People have access to more information than they know what to do with. We spent all the time collating information, while we ought to be taking action. Every dream has a cost in action, and that's why 👇&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The phrase You can be anything is a scam&lt;/strong&gt; and a corporate ideology to get you to aspire for more, work for more, spend more, and keep the cycle going. &lt;strong&gt;You can’t be anything you want&lt;/strong&gt;. This shouldn’t be surprising, by birth, you are already limited either by geography, genes, or family lineage. Comparing yourself to Elon Musk, Oprah, or a random person you saw their flashy life online is the gateway to misery. Focus on the step in front of you. Take that and then worry about the next one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Every dream/goal is a judge&lt;/strong&gt;. Everything you want is something you lack. Logically, this would mean the higher the distance between your dreams and your current self is, the more miserable/unsatisfied you are with your current self. You have two options: be realistic with your goals or improve your current life faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It’s okay to be Normal.&lt;/strong&gt; Normal is actually where most people would end up based on several factors. Sometimes the hustle of fighting this is more hurtful than being Normal itself. Every goal/aspiration that is not backed up with the appropriate resources is a wish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do not be afraid to try.&lt;/strong&gt; Change of tone from the previous ones. But do not be afraid to break things. I have tried at least 4 businesses over the past 2 years. It doesn’t matter how much of it is successful; in the end, you only need one. Explore new things. Listen to music outside your playlist(&lt;strong&gt;I am listening to Terry Apala while writing this&lt;/strong&gt;, I’m serious). Read outside your field. Ask uninteresting questions. Break patterns. Go outside your norms, even if just for the fun of it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t live in isolation&lt;/strong&gt;. Find love if you can, and embrace genuine friendship if you have one. At minimum, be at peace with your neighbour. Life is so much easier with the right people beside you. Sorry to say this, but your online friends/community is not the same. I couldn't care less about your number of followers if no one is there for you in your low moments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>productivity</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Domain-Driven Architecture: Blueprint for Scalable Systems Part 2</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Wed, 14 May 2025 16:14:00 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/domain-driven-architecture-blueprint-for-scalable-systems-part-2-2l8a</link>
      <guid>https://forem.com/fredrick_oladipupo/domain-driven-architecture-blueprint-for-scalable-systems-part-2-2l8a</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/fredrick_oladipupo/domain-driven-architecture-a-blueprint-for-scalable-systems-2fle"&gt;&lt;strong&gt;In Part 1&lt;/strong&gt;&lt;/a&gt;, we laid the groundwork, exploring what Domain-Driven Architecture (DDA) is, why it matters, and how concepts like Bounded Contexts, Ubiquitous Language, and Aggregates shape the structure of your system.&lt;/p&gt;

&lt;p&gt;In this second part, we’ll focus to how DDA pays off in the real world, especially when it comes to scalability and maintainability. You’ll see how designing around the domain, instead of frameworks or databases, leads to systems that are easier to scale, evolve, and reason about over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We will explore:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How DDA improves Scalability and Maintainability&lt;/li&gt;
&lt;li&gt;Real-World Example of organisation using DDA from Amazon to Netflix&lt;/li&gt;
&lt;li&gt;Best Practices when Implementing DDA&lt;/li&gt;
&lt;li&gt;Scenarios where DDA might not be the optimal choice&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How DDA Improves Scalability and Maintainability&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Clear System Boundaries:&lt;/em&gt; DDA encourage splitting systems into &lt;em&gt;bounded contexts&lt;/em&gt;, each with its own &lt;em&gt;domain&lt;/em&gt; logic and can be manage by independent Teams with clear boundaries and unpolluted domains. This aligns with micro-service and modular systems architectures.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Easier Scaling:&lt;/em&gt; Each service in DDA can be scaled independently based on demand.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Separation of concerns to reduce complexity:&lt;/em&gt; Each bounded context encapsulates its own data and logic. Each service is kept simple, this makes changes easier to isolate and test.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Lower Operational Costs:&lt;/em&gt; Systems remain leaner, reducing infrastructure overhead.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Real-World Example of Organisations using DDA&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Netflix&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Netflix began as a monolithic application but, after a major outage in 2008, embarked on a journey to decompose its system into microservices. DDD was central to this process, guiding the identification of business domains and the creation of bounded contexts-each mapped to a set of micro-services responsible for a specific business capability, such as user management, content catalog, recommendations, and playback&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uber&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uber’s journey from a monolithic architecture to a highly distributed system is a textbook example of how Domain-Driven Design (DDD) principles can be applied-and adapted-at extreme scale. Uber evolved from a single, monolithic codebase to a system with over 2,200 micro-services. As system complexity grew, Uber adopted a Domain-Oriented Microservice Architecture (DOMA), drawing heavily from DDD, Clean Architecture, and other established patterns. The process was documented &lt;a href="https://www.uber.com/en-GB/blog/microservice-architecture/" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Amazon&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/mt/find-your-business-domains-to-start-refactoring-monolithic-applications/" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt;, both as a retailer and as a cloud provider (AWS), has embraced Domain-Driven Design (DDD) principles to manage the complexity of its vast, evolving systems. DDD has played a key role in Amazon’s shift from monolithic architectures to distributed micro-services, helping align software with business domains and enabling scalable, resilient, and agile systems&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices for Implementing DDA&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Clear Boundaries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure each &lt;em&gt;bounded context&lt;/em&gt; has distinct responsibilities. Create boundaries between your domain model and external systems. Keep your domain clean and focused, prevent non-domain concepts from polluting your model. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Establish a Ubiquitous Language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a shared language that is used consistently by developers, domain experts, and stakeholders. Use this language in the code, documentation, and discussions to avoid misunderstandings and ensure alignment. This minimises misunderstandings and ensures software model matches the business use-cases. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Collaborate with Domain Experts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Work directly with domain experts to gain a deep understanding of the business domain. In fact, it is a futile effort to try and  implement DDA without a domain expert. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Domain events and Event-Driven Communication:&lt;/strong&gt; To avoid redundant and unnecessary coupling, use domain events to track and react to significant changes within the domain while Keeping services loosely coupled for better scalability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimize with CQRS:&lt;/strong&gt; Separate read and write concerns to boost performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage Aggregates Smartly:&lt;/strong&gt; Group entities logically to maintain data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document Everything:&lt;/strong&gt; A well-documented domain model ensures teams stay aligned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not over-engineer - Don’t apply DDD to simple projects with little domain complexity. It can introduce unnecessary overhead.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;When DDA Might Not Be the Best Choice&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While &lt;em&gt;Domain-Driven Design (DDA)&lt;/em&gt; is powerful and provides structure and scalability, it’s not a silver bullet and sometimes DDA might not be the right choice for your project and could introduce unnecessary complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A non-exhaustive list of scenarios where DDA might not be necessary—or even problematic:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Small or Simple Applications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example: A basic CRUD (Create, Read, Update, Delete) application with no complex business logic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDA introduces extra complexity (bounded contexts, aggregates, domain events, etc.), which is an overkill for a straightforward app.&lt;/li&gt;
&lt;li&gt;A simple MVC or layered architecture is more efficient.&lt;/li&gt;
&lt;li&gt;Use a traditional monolithic approach with clear service layers instead of a full-fledged DDA structure.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;2. Early-Stage Startups or Fast Prototyping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example: A startup building an &lt;strong&gt;MVP (Minimum Viable Product)&lt;/strong&gt; that needs rapid iteration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDA slows down development due to the need for extensive domain modeling and bounded contexts.&lt;/li&gt;
&lt;li&gt;The business logic might change frequently, making the initial DDA investment wasteful.&lt;/li&gt;
&lt;li&gt;Start with a modular monolith and introduce DDA concepts gradually if complexity increases.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;3. When the Business Domain Is Not Well Understood&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example: A new industry or business model where the rules, processes, and workflows are still evolving.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDA requires deep domain knowledge upfront.&lt;/li&gt;
&lt;li&gt;If the business keeps changing, the domain model might need constant restructuring, leading to wasted effort.&lt;/li&gt;
&lt;li&gt;Begin with a simpler, iterative approach, and introduce domain-driven concepts once the business logic stabilises.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;4. Performance-Critical, High-Throughput Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example: A real-time stock trading platform or video streaming service that needs ultra-low latency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDA prioritises domain consistency over performance, which can introduce overhead (extra layers, event processing, etc.).&lt;/li&gt;
&lt;li&gt;Aggregates and repositories may slow down high-volume, high-speed operations.&lt;/li&gt;
&lt;li&gt;Use a data-driven architecture or event-sourcing to optimize for speed, and selectively apply DDA where business logic is critical.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;5. Teams Without Strong DDA Experience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A team unfamiliar with aggregates, bounded contexts, and domain events trying to implement DDA for the first time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steep learning curve - misuse of DDA can add confusion instead of solving problems.&lt;/li&gt;
&lt;li&gt;Over-engineering risk - developers might introduce unnecessary complexity without clear benefits.&lt;/li&gt;
&lt;li&gt;Start with basic domain modeling and introduce DDA principles gradually rather than applying them everywhere at once.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Domain-Driven Design isn’t just a technical approach, it’s a mindset shift. By structuring software based on business realities, teams can build &lt;em&gt;scalable, maintainable, and resilient systems&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For large, evolving applications, DDA serves as a &lt;em&gt;blueprint for long-term success&lt;/em&gt;. But like any tool, its effectiveness depends on when and how it’s applied.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Further Reading &amp;amp; Resources&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;📖 &lt;strong&gt;Books:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Domain-Driven Design” by &lt;strong&gt;Eric Evans&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;“Implementing Domain-Driven Design” by &lt;strong&gt;Vaughn Vernon&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;strong&gt;Articles &amp;amp; Guides:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cerbos.dev/blog/determining-service-boundaries-and-decomposing-monolith" rel="noopener noreferrer"&gt;Netflix and DDA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/news/2015/09/domain-events-consistency" rel="noopener noreferrer"&gt;&lt;strong&gt;Jan Stenberg. Domain Events and Eventual Consistency&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;Event-Driven Architecture &amp;amp; DDA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/tags/domain%20driven%20design.html" rel="noopener noreferrer"&gt;DDA in Microservices - Martin Fowler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=JHGkaShoyNs" rel="noopener noreferrer"&gt;Greg Young on CQRS &amp;amp; Event Sourcing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf#page=25" rel="noopener noreferrer"&gt;&lt;strong&gt;Greg Young. What is a Domain Event?&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation" rel="noopener noreferrer"&gt;&lt;strong&gt;Domain events: Design and implementation in .Net&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>programming</category>
      <category>performance</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Domain-Driven Architecture: A Blueprint for Scalable Systems - PART 1</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Tue, 15 Apr 2025 10:45:22 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/domain-driven-architecture-a-blueprint-for-scalable-systems-2fle</link>
      <guid>https://forem.com/fredrick_oladipupo/domain-driven-architecture-a-blueprint-for-scalable-systems-2fle</guid>
      <description>&lt;p&gt;As systems grow in complexity, traditional development approaches struggle to keep up. Codebases become tangled, business logic gets scattered across layers, and scaling introduces bottlenecks. &lt;strong&gt;Domain-Driven Architecture (DDA)&lt;/strong&gt; offers a structured approach to tackling this complexity, ensuring that software effectively mirrors real-world business problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DDA&lt;/strong&gt; is not suitable for simple applications. However, when building &lt;strong&gt;medium to large scale&lt;/strong&gt; &lt;strong&gt;systems&lt;/strong&gt; or &lt;strong&gt;enterprise applications&lt;/strong&gt;, adopting DDA can make your system &lt;strong&gt;scalable, maintainable, and aligned with business goals&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When working with Domain-driven architecture, Your goal isn’t just to build a CRUD system. You’re modeling how the physical business shop works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Throughout this article, I will use &lt;strong&gt;DDA or DDD&lt;/strong&gt; as the shorthand for Domain-driven architecture/design. To make things a bit easier, I will use &lt;strong&gt;Fred and son’s shoe&lt;/strong&gt; an imaginary e-commerce company as a case study. Fred and son’s shoe is a one stop shop for shoes in Ilora, Nigeria.&lt;/p&gt;

&lt;p&gt;This topic is broken down into two articles. In this article, we will explore the core concepts of DDA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domains&lt;/li&gt;
&lt;li&gt;Sub-domains&lt;/li&gt;
&lt;li&gt;Bounded Context&lt;/li&gt;
&lt;li&gt;Entities&lt;/li&gt;
&lt;li&gt;Value Objects&lt;/li&gt;
&lt;li&gt;Aggregates and aggregates roots&lt;/li&gt;
&lt;li&gt;Domain events&lt;/li&gt;
&lt;li&gt;Command Query Responsibility Segregation (CQRS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Core Concepts of Domain-Driven Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Domains&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;domain&lt;/strong&gt; represents the &lt;strong&gt;core problem space&lt;/strong&gt; a business operates in. That’s a fancy way of saying Domain is the core idea your business is built on. The problem you are solving for your customer. For Fred and sons shoe, our domain is shoe sales.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your domain is the core business logic that rules the software — not the tech stack, not the UI, but the &lt;strong&gt;rules, goals, and behaviour&lt;/strong&gt; of the organisation or problem you're addressing. The most important part of your business that gives you competitive advantage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What to note when defining your domain&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your domain must reflects business goals and rules. When defining domain, this is not the time to think about the technical details, the focus should be on what the problems are and how to go about solving them. Technical concerns like tech stack, database choice or infra decisions can wait. The focus is here is core problem definition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domains should be defined by business expert&lt;/strong&gt;, People who understood what the primary focus of the business is. They can be supported by developers to ensure accurate representation and language.&lt;/li&gt;
&lt;li&gt;Try to use common set of terms shared by devs and domain experts as much as possible (e.g., "Order", "Customer", "Customer discount Points"). This will make communication across teams and units easier and processes faster.&lt;/li&gt;
&lt;li&gt;Domain is not just data, but behaviour — e.g., “Apply discount,” “Mark order as fulfilled,” “Calculate tax.”, “Cancel order”&lt;/li&gt;
&lt;li&gt;Domain can evolve. You are not stuck with a definition forever - As the &lt;strong&gt;business grows, domain **evolves&lt;/strong&gt; too — e.g. adding delivery support, new pricing strategies, or international shipping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A well defined domain will guide developers in building systems that aligns with the business goals. The &lt;strong&gt;business should drive the technical requirements&lt;/strong&gt; not the other way around.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Subdomains
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;subdomain&lt;/strong&gt; is a distinct, smaller and  focused part of the main domain that manages a specific business function. &lt;strong&gt;DDA&lt;/strong&gt; advocates breaking down domain into subdomains to handle complexity and better align code with business logic. &lt;/p&gt;

&lt;p&gt;Each subdomain operates &lt;strong&gt;independent yet interconnected&lt;/strong&gt;, enabling teams to work on specific areas without disrupting the broader system. Subdomain must have a clear and defined boundary - that separates it from other Subdomains. &lt;/p&gt;

&lt;p&gt;Using our e-commerce example, here are some subdomains we could come up with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Product Catalog Subdomain&lt;/strong&gt;: Handles product listings, categories, attributes (e.g., size, color), and availability.&lt;br&gt;
Example: Add new product, Filter by category, Show out-of-stock items&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; &lt;strong&gt;Ordering Subdomain&lt;/strong&gt;: Manages the shopping cart, order creation, and order tracking. &lt;br&gt;
Example: Add to cart, Place an order, Track order status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payment Subdomain&lt;/strong&gt;: Handles payment processing, refunds, and invoices.Example: Process credit card, Initiate refund, Send invoice email.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shipping Subdomain&lt;/strong&gt;: Deals with delivery options, tracking shipments, and managing logistics. Example: Calculate shipping fee, Update delivery status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customer Management Subdomain&lt;/strong&gt;: Stores customer profiles, preferences, and support interactions.Example: Update address, View order history, Open support ticket&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Bounded Contexts&lt;/strong&gt;:
&lt;/h3&gt;

&lt;p&gt;A bounded context defines &lt;strong&gt;clear (technical) boundaries&lt;/strong&gt; within a system, ensuring that each subdomain has its own independent logic, rules, and data models. A model within a specific context behaves consistently across all use cases within the boundary. &lt;/p&gt;

&lt;p&gt;This is probably the most task intensive part of DDA. It requires effort and time to map domain to the appropriate context and even more energy and skills to ensure teams respect the boundaries and avoid function overlap (A situation where two or more part of a domain is doing the same thing).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Ordering&lt;/strong&gt; service tracks items and quantities.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Payments&lt;/strong&gt; service only deals with transactions and invoices.&lt;/li&gt;
&lt;li&gt;They communicate via &lt;strong&gt;APIs or message queue services&lt;/strong&gt; but &lt;strong&gt;don’t share databases&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When bounded context is done properly it ensures&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: It isolates different parts of a system to reduce complexity and improve maintainability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarity&lt;/strong&gt;: Each context uses a consistent language (Ubiquitous Language), avoiding ambiguities in terminology.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt;: Enables independent evolution, scaling, and deployment of components, especially in micro services architecture&lt;/li&gt;
&lt;li&gt;It reduces &lt;strong&gt;code sprawl&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How is bounded context different from subdomains?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As we get deeper, I would like to take a pause and clarify this before it gets confusing.  Many times, bounded contexts and subdomains are misinterpreted and can lead to confusion. Below are the core differences between the two.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Problem space vs Solution Space&lt;/strong&gt;&lt;br&gt;
A Subdomain exists in the problem space. It represents specific areas of the business domain (e.g., billing, inventory) that need to be taken care of. On the other hand, Bounded Context exists in the solution space, it defines technical boundaries where a consistent domain model is applied to solve problems within a subdomain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;br&gt;
Sub domain goal is to divides the core domain into smaller manageable parts. While bounded context ensures integrity of domain by defining clear boundaries, preventing ambiguity in terms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hierarchy&lt;/strong&gt;:&lt;br&gt;
Subdomains are conceptual and often considered “above” bounded contexts because they represent business concerns. Bounded Contexts are design to implement subdomains in code, making them more technical and solution-oriented&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Entities and Value Objects&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;p&gt;Entities are part of the core concept in a domain, They are identified by their unique identities and so they are distinguishable from other objects even if their attributes changed over their lifecycle, Their unique identities remain the same. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Few details that can help you understand entities&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities are domain objects defined by unique identifier e.g ID, UUID. This identity is persisted regardless of changes to their attributes&lt;/li&gt;
&lt;li&gt;They are &lt;strong&gt;persisted over time&lt;/strong&gt; (e.g., a &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt;, or &lt;code&gt;Product&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;They are &lt;strong&gt;mutable&lt;/strong&gt; and they change over their life cycle.&lt;/li&gt;
&lt;li&gt;Their identities and continuity of the object are crucial, take tracking the same customer across transaction for example.&lt;/li&gt;
&lt;li&gt;Example is  “a customer” entity with a unique customer ID or a customer wallet entity with a unique wallet ID&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Value Objects&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;On the other hand, value objects are immutable. This mean they do not change throughout their lifecycles. They do not have identities, and are defined solely by their attributes. Two value objects with the same attributes are considered equal. Example: Two addresses with the same street name, postcode, and country are considered the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Characteristics of value objects&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Value objects are the descriptive part of the domain.&lt;/li&gt;
&lt;li&gt;They are defined by their attributes.&lt;/li&gt;
&lt;li&gt;Because of their lack of identity,  they are interchangeable, value objects with the same attributes can be technically identify as one.&lt;/li&gt;
&lt;li&gt;They are immutable - They cannot change once created&lt;/li&gt;
&lt;li&gt;When thinking of value objects, think of currency, or a price of a product, or address of a customer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How do you decide whether to use an entity or a value object in your domain model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you are confused on what to use, ask your self the question below&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identity:

&lt;ul&gt;
&lt;li&gt;Entity - Has a unique identifier&lt;/li&gt;
&lt;li&gt;Value objects - No unique identifier, it is defined by its attributes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Mutable

&lt;ul&gt;
&lt;li&gt;Entity - They are mutable (changed)&lt;/li&gt;
&lt;li&gt;Value objects - Immutable, once created they remain same through their life cycle&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Equality

&lt;ul&gt;
&lt;li&gt;Entity - Equality is based on identity&lt;/li&gt;
&lt;li&gt;Value objects - Equality is based on attribute values&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Aggregates and Aggregate Roots&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;aggregate&lt;/strong&gt; is a cluster of entities and value objects that are related and are treated as a &lt;strong&gt;single unit&lt;/strong&gt;. Aggregate encapsulates all the details of the unit and only expose required functionalities to the rest of the system through the aggregate root.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aggregate root&lt;/strong&gt; is the main entry point for interacting with data in an aggregate. Likewise, only aggregate root interacts with external systems. This ensures consistency and enforces business rules across the unit.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of an aggregate as a mansion with lots of goodies inside &lt;strong&gt;(Entities and value objects)&lt;/strong&gt;. This mansion has a single golden gate &lt;strong&gt;(Aggregate root)&lt;/strong&gt; which is the only entrance. To get something out or interact with the mansion you need to pass through this gate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now a bit technical - Using Delivery as an example in Fred’s shoe. &lt;br&gt;
Delivery Manager is an aggregate - entities are: delivery items, customer details, and address, total price, discount code as value objects. You wouldn’t let the outside world change individual Delivery item or price directly. Instead, they go through the aggregate root &lt;strong&gt;DeliveryManager.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DeliveryManager.addItem(product, quantity)
DeliveryManager.removeItem(productId)
DeliveryManager.applyDiscount(code)
DeliveryManager.changeDeliveryTime(newDateTime)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an important concepts in DDA and it helps to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protects your data&lt;/strong&gt; from being changed in weird ways.&lt;/li&gt;
&lt;li&gt;Keeps your system &lt;strong&gt;easy to reason about&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Makes your code &lt;strong&gt;more reliable&lt;/strong&gt; in big systems.&lt;/li&gt;
&lt;li&gt;Prevents &lt;strong&gt;inconsistent writes and race conditions&lt;/strong&gt; in high-load environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Domain Events&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What are domain events ?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Event&lt;/strong&gt; are occurrence that has happened in the past. Like your birthday or in our e-commerce example, a shoe purchase. Think of domain events in the same way. &lt;strong&gt;Domain events&lt;/strong&gt; are events that capture significant business occurrences in a domain that other aggregates/parts of the system might need to react to.&lt;/p&gt;

&lt;p&gt;Domain events enable better separation of concerns among different parts of a domain. Instead of tightly coupling services, events enable loose coupling and &lt;strong&gt;asynchronous processing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How are domain events different from traditional message events ?&lt;/strong&gt;&lt;br&gt;
Domain events are similar to event message style but also different in one way.  With event messaging service like: message queue, message broker or even a service bus (link to the previoud article here),  messages are always sent asynchronously and communication are available to different process and machine.&lt;/p&gt;

&lt;p&gt;They are not bounded by the boundary context of the domain.  On the other hand, with domain event, domain events are raise from a domain operation in progress and wants side effects/reaction to it by other process operating &lt;strong&gt;within the same domain.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Likewise, in a traditional messaging system, messages can be produced without a consumer or a reaction. Domain events are quite different as you most certainly only emit events because you want a reaction. In some instances, you also want to treat those reactions as a database transaction where either all the operations related to a domain event finish successfully or none of them do.&lt;/p&gt;

&lt;p&gt;For example - Imagine a situation at Fred’s shoe store - An order was placed using a gift card and a discount code was used and it emits an event - You want reactions to the event to: Update the stock count, nullify the discount code so it is not re-used and also manage the customer gift card balance among other things.&lt;/p&gt;

&lt;p&gt;Lastly, Domain events and their reactions (the actions triggered afterwards that are managed by event handlers) should occur almost immediately, and within the same domain.  Domain event can handled synchronously if necessary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In DDA,  use domain events to explicitly implement side effects across one or multiple aggregates within a domain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;6. Command Query Responsibility Segregation (CQRS)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Command Query Responsibility Segregation (CQRS) is a design pattern that segregates write and read actions for a data store into separate data models. This means a single data store would have two model interfaces. One to manager &lt;strong&gt;write operations&lt;/strong&gt; and the other for &lt;strong&gt;read operations&lt;/strong&gt;. It is important to note that CQRS is not limited to DDA. Other software pattern and architecture can leverage CQRS if the project demands it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: While CQRS is a powerful tool for DDA, it introduces more complexity to your system. It is only beneficial and it is advisable to only use it if your system requires it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Only use CQRS if your your system meets one or more of the following:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your domain is complex&lt;/strong&gt;, requiring distinct models for handling reads and writes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and performance&lt;/strong&gt; are critical concerns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your system requires flexibility&lt;/strong&gt; to evolve over time without disrupting existing functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You are not building for a simple domain or CRUD-style applications&lt;/strong&gt; CQRS may introduce unnecessary complexity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You have separation of development concerns within the same model.&lt;/strong&gt; With CQRS a team can work on complex business logic in the write model, and another team develops the read model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Divergent Data Requirements&lt;/strong&gt;: In large applications, there are instances where read and write operations have different data requirements. To place an order at Fred’s shoe you  need the customerId, productId and the quantity. On the other hand, to read an order, you need the full customerDTO and the productDTO. These two operations demand to different model from the same data store.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A banking system may have **one database for handling transactions (writes). Another optimised database for quickly retrieving account balances (reads).This pattern optimises API performance and reduces database contention.&lt;/p&gt;

&lt;p&gt;This is the first installment of the two part series on DDA&lt;br&gt;
&lt;strong&gt;In the second part&lt;/strong&gt;, we will talk about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How DDA Improves Scalability and Maintainability&lt;/li&gt;
&lt;li&gt;Examples of Companies using DDA and how they are using it&lt;/li&gt;
&lt;li&gt;Best Practices for Implementing DDA&lt;/li&gt;
&lt;li&gt;When DDA might not be the best choice&lt;/li&gt;
&lt;li&gt;A personal story&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Further Reading &amp;amp; Resources&lt;/strong&gt;&lt;br&gt;
📖 &lt;strong&gt;Books:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain-Driven Design by &lt;strong&gt;Eric Evans&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Implementing Domain-Driven Design by &lt;strong&gt;Vaughn Vernon&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;strong&gt;Articles &amp;amp; Guides:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain-Driven Design in Micro-services&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/news/2015/09/domain-events-consistency" rel="noopener noreferrer"&gt;&lt;strong&gt;Jan Stenberg. Domain Events and Eventual Consistency&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;Event-Driven Architecture &amp;amp; DDA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/tags/domain%20driven%20design.html" rel="noopener noreferrer"&gt;DDA in Microservices - Martin Fowler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=JHGkaShoyNs" rel="noopener noreferrer"&gt;Greg Young on CQRS &amp;amp; Event Sourcing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf#page=25" rel="noopener noreferrer"&gt;&lt;strong&gt;Greg Young. What is a Domain Event?&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation" rel="noopener noreferrer"&gt;&lt;strong&gt;Domain events: Design and implementation in .Net&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Photo by &lt;a href="https://unsplash.com/@joakimnadell?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Joakim Nådell&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/grayscale-photo-of-low-angle-view-of-building-K67sBVqLLuw?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>backend</category>
      <category>webperf</category>
      <category>architecture</category>
    </item>
    <item>
      <title>API PERFORMANCE</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Fri, 11 Apr 2025 08:46:02 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/-19fl</link>
      <guid>https://forem.com/fredrick_oladipupo/-19fl</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d" class="crayons-story__hidden-navigation-link"&gt;Optimizing API Performance Part 3: Asynchronous Processing &amp;amp; Queues&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/fredrick_oladipupo" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2940427%2F92331d7f-d347-4a1c-b9f0-ecc82badcfeb.jpg" alt="fredrick_oladipupo profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/fredrick_oladipupo" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Fredrick Oladipupo
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Fredrick Oladipupo
                
              
              &lt;div id="story-author-preview-content-2368822" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/fredrick_oladipupo" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2940427%2F92331d7f-d347-4a1c-b9f0-ecc82badcfeb.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Fredrick Oladipupo&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 31 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d" id="article-link-2368822"&gt;
          Optimizing API Performance Part 3: Asynchronous Processing &amp;amp; Queues
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webperf"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webperf&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/backenddevelopment"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;backenddevelopment&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>programming</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Optimizing API Performance Part 3: Asynchronous Processing &amp; Queues</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Mon, 31 Mar 2025 12:47:42 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d</link>
      <guid>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d</guid>
      <description>&lt;p&gt;This is the 3rd instalment on the API performance and optimisation series. It is targeted at medium scale to enterprise level applications.  We have explore &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-1-caching-4fe4"&gt;Caching&lt;/a&gt; in part 1 of the series, and  &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-2-load-balancing-3ie5"&gt;load balancing&lt;/a&gt; in part 2.  In this article, we will dive into asynchronous processing and how it can help makes your API &lt;strong&gt;faster&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt; and more &lt;strong&gt;resilient&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;We will explore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Why Asynchronous Processing Matters&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Benefits of  Asynchronous Processing and queues to your API&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How Asynchronous Processing works with queues&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Popular Message Queues for Asynchronous Processing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practical Use Cases of Asynchronous Processing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best Practices for Asynchronous Processing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resources for further reads&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. The problem statement (&lt;strong&gt;Why Asynchronous Processing Matters).&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most applications start with &lt;strong&gt;synchronous REST APIs&lt;/strong&gt;, where Service A makes a request and waits for Service B to respond. However, as application grows this becomes a problem. &lt;/p&gt;

&lt;p&gt;Using e-commerce applications as a case study, a click to purchase an item can trigger calls to: process payments, send emails, update stock count  and inventory, update suggested products data, update dashboard reports in real-time. Without any form of asynchronous processing, The API process everything synchronously before returning a response.&lt;/p&gt;

&lt;p&gt;This often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Degrades application performance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increase server load&lt;/strong&gt; – More CPU and memory usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Results in slow API response times&lt;/strong&gt; – Users wait longer for a response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lead to potential failures&lt;/strong&gt; – A delay in one step (e.g., slow email service) can crash the entire request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creates bottlenecks&lt;/strong&gt; – A delayed response from your email provider will put rest of the processes on hold.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Solution: Offloading Heavy and non urgent Tasks to a Queue&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of making users wait, APIs can &lt;strong&gt;process tasks asynchronously&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;API &lt;strong&gt;receives a request&lt;/strong&gt; (e.g., "Place Order").&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API &lt;strong&gt;queues background tasks&lt;/strong&gt; (e.g., email notifications, inventory update, analytics).&lt;/li&gt;
&lt;li&gt;API &lt;strong&gt;immediately responds&lt;/strong&gt; to the user.&lt;/li&gt;
&lt;li&gt;Background tasks are &lt;strong&gt;processed separately&lt;/strong&gt;, without slowing the API.&lt;/li&gt;
&lt;li&gt;This makes APIs &lt;strong&gt;blazing fast&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, and &lt;strong&gt;resilient under heavy load&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. Benefits of  Asynchronous Processing and queues to your applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improved Performance &amp;amp; Responsiveness&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Offloading time-consuming tasks (e.g., sending emails, processing payments) to background workers ensures your API responds instantly to users instead of making them wait.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Better Scalability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queues help distribute workloads across multiple workers, preventing bottlenecks and allowing your system to handle more requests without overwhelming resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fault Tolerance &amp;amp; Reliability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a request fails due to a temporary issue (e.g., network failure), queued tasks can be retried automatically, reducing the risk of data loss or failed operations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Efficient Resource Utilization&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of blocking API threads with long-running operations, background workers process tasks at a controlled pace, optimising CPU and memory usage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Decoupled Architecture&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queues enable micro-services and different system components to communicate asynchronously, improving modularity and reducing dependencies between services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improved User Experience&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users don’t have to wait for slow operations (like file processing or third-party API calls) to complete before getting a response, making applications feel faster and smoother.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. How Message Queues Work&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We have highlighted that asynchronous processing allows applications become more resilient by handling important/urgent tasks immediately and queue the rest for a later time. They do this by storing tasks and relevant data in a message queue system like RabbitMQ or Apache Kafka to be processed or read at a later time.&lt;/p&gt;

&lt;p&gt;Message queue systems are robust and serve different use cases. Apache Kafka for example ensure reliability and persistence of data even across reads.  However, Kafka doesn’t care whether there is a consumer for a message or if consumer reads a message. On other hand, RabbitMQ is more involved in the life span of the message, ensuring it gets to the right consumer in the right order. &lt;/p&gt;

&lt;p&gt;Irrespective of the type of message queues you are working with, there are three common themes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;&lt;em&gt;producer&lt;/em&gt;&lt;/strong&gt; -  application that sends messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queue (RabbitMQ, AWS SQS)&lt;/strong&gt; - a buffer that stores messages.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;em&gt;consumer&lt;/em&gt;&lt;/strong&gt; - application that receives/read messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using our order process example - The order service produce the message to send email, update inventory, and so on. The respective services receive the message or read the message from the broker then perform actions as required of them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; &lt;strong&gt;Message Queue systems&lt;/strong&gt; are capable of handling variety of process complexity. From simple process like a pub/sub messaging system to a complex streaming and Remote procedure call (RPC). However, your use case would determine how and which to use.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Popular Message Queues:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt; (for lightweight, fast task queues).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RabbitMQ&lt;/strong&gt; (for enterprise-grade messaging)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Kafka&lt;/strong&gt; (for large-scale event streaming) - think something big like a sport-book service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS SQS&lt;/strong&gt; (fully managed message queue) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Others -&lt;/strong&gt; Apache ActiveMQ, KubeMQ, Celery, IBM MQ etc.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. Practical Use Cases of Asynchronous Processing&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Sending Emails Without Blocking the API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of waiting for an email service to respond, &lt;strong&gt;queue the task&lt;/strong&gt; and return a response immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example (Using Node.js &amp;amp; Redis Queue – BullMQ)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bullmq&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emailQueue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/send-email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email request received!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Worker: Processes emails in the background&lt;/span&gt;
&lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userEmail&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userEmail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to send email: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;2. Processing Payments Without Slowing Checkout&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;E-commerce platforms queue payment tasks so API responses are &lt;strong&gt;instant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API places order and &lt;strong&gt;queues payment processing&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The response is &lt;strong&gt;immediate&lt;/strong&gt; (user doesn’t wait).&lt;/li&gt;
&lt;li&gt;A background worker &lt;strong&gt;handles the payment asynchronously&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Shopify processes &lt;strong&gt;millions of orders daily&lt;/strong&gt;, especially on &lt;strong&gt;Black Friday&lt;/strong&gt;, where traffic surges &lt;strong&gt;10x&lt;/strong&gt;. By &lt;strong&gt;queuing payments&lt;/strong&gt;, they reduced checkout times by &lt;strong&gt;40%&lt;/strong&gt;, preventing crashes and improving conversions.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Generating Reports in the Background&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of making users wait, APIs can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accept the request&lt;/strong&gt; &amp;amp; enqueue report generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send a notification/email&lt;/strong&gt; when the report is ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Google Analytics queues data processing so reports are generated without blocking real-time insights.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4. Updating stock Inventory&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of making users wait, APIs can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accept the request&lt;/strong&gt; &amp;amp; enqueue report generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send a notification/email&lt;/strong&gt; when the report is ready.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Best Practices for Asynchronous Processing&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose the right queue&lt;/strong&gt; – Redis for speed, RabbitMQ for reliability, Kafka for streaming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set task priorities&lt;/strong&gt; – If possible, Process urgent tasks first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor failed jobs&lt;/strong&gt; – Implement retries and logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-scale workers&lt;/strong&gt; – Handle increased load dynamically.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Make Your APIs Lightning Fast&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Asynchronous processing and queues &lt;strong&gt;remove bottlenecks, improve scalability, and enhance user experience&lt;/strong&gt;. Whether you're handling &lt;strong&gt;emails, payments, or heavy computations&lt;/strong&gt;, &lt;strong&gt;queues make APIs smoother and more resilient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How do you handle background tasks in your APIs? Drop a comment below!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Further Reading &amp;amp; Resources&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://docs.bullmq.io/" rel="noopener noreferrer"&gt;BullMQ – Redis Queue for Node.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ – Messaging Broker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://aws.amazon.com/sqs/" rel="noopener noreferrer"&gt;AWS SQS – Fully Managed Queue&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗&lt;a href="https://aws.amazon.com/compare/the-difference-between-rabbitmq-and-kafka" rel="noopener noreferrer"&gt;AWS RabbitMQ and Apache Kafka&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>programming</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Optimizing API Performance – Part 2: Load Balancing</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Tue, 25 Mar 2025 11:04:53 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-2-load-balancing-3ie5</link>
      <guid>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-2-load-balancing-3ie5</guid>
      <description>&lt;p&gt;APIs are the backbone of modern applications, handling thousands (or even millions) of requests daily. But as traffic grows, a single server can quickly become overwhelmed, leading to &lt;strong&gt;slow responses, timeouts, crashes&lt;/strong&gt; and ultimately &lt;strong&gt;loss in business revenue&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;load balancing&lt;/strong&gt; comes in. Load balancers are capable of &lt;strong&gt;distributing traffic across multiple servers&lt;/strong&gt;, ensuring your API remains &lt;strong&gt;fast, scalable, and highly available&lt;/strong&gt;. This tutorial is part of a series on Optimising api performance. You can read part 1 of this series on Caching &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-1-caching-4fe4"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In this guide, we’ll explore:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;When you should consider load balancing in your application&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How load balancing works&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Load balancing strategies&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-World Case Study: PayU&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Common load balancing issues and fixes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best practices&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conclusion &amp;amp; Resources&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. When Should I consider Load Balancing?
&lt;/h2&gt;

&lt;p&gt;Not every API needs load balancing from day one. But you should strongly consider it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Your API receives 1,000+ requests per second.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Your server CPU usage consistently exceeds 70%.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You need high availability&lt;/strong&gt; (e.g., financial transactions, streaming)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You’ve experienced downtime due to traffic spikes -&lt;/strong&gt; Those graphs are telling you something&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Reliability  -&lt;/strong&gt; Robust Load balancer like &lt;strong&gt;Elastic load balancer&lt;/strong&gt; are capable of performing health checks on upstreams servers before distributing requests - helping maximise performance and resiliency.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You need an added layer of Security -&lt;/strong&gt; Load balancers are capable of playing crucial role in security. They are capable of acting as a buffer against DDoS attacks, and enabling features like SSL encryption and WAF integration. &lt;/li&gt;
&lt;li&gt;Likewise, Load balancers can be instructed to drop requests from suspicious source. Ensuring these malicious requests do not reach your core application resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these apply to your system, it’s time to implement a &lt;strong&gt;load balancer.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. How Load Balancing Works
&lt;/h2&gt;

&lt;p&gt;A load balancer acts as a middle layer between clients and backend servers. It distributes incoming networks and or application requests across multiple servers  or "targets" based on predefined rules. &lt;/p&gt;

&lt;p&gt;Load balancer prevents overload and improve performance, availability, and scalability of an application.  Load balancer acts as a single point of contact for clients, routing requests to healthy servers and monitoring their health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without load balancing: Requests go to &lt;strong&gt;one server&lt;/strong&gt;, which can get overloaded.&lt;/li&gt;
&lt;li&gt;With load balancing: Requests are &lt;strong&gt;spread across multiple servers&lt;/strong&gt;, improving speed and reliability and make it easy to scale.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a &lt;strong&gt;basic visualisation&lt;/strong&gt; of how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Requests  ---&amp;gt;  Load Balancer  ---&amp;gt;  Server 1
                                      ---&amp;gt;  Server 2
                                      ---&amp;gt;  Server 3

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Nginx as a Load Balancer *&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http {
    upstream backend_servers {
        server api-server-1.local;
        server api-server-2.local;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://backend_servers;
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup distributes requests between &lt;strong&gt;api-server-1.local&lt;/strong&gt; and &lt;strong&gt;api-server-2.local&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Load Balancing Strategies
&lt;/h2&gt;

&lt;p&gt;Load balancing strategies are methods or techniques load balancer uses in distributing network or application traffic across multiple targets. This strategy defines the rules to optimize resource utilisation, improve performance, and enhance reliability of the system as a whole. We will explore few of the common strategies below.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Round Robin (Default &amp;amp; Simple)
&lt;/h3&gt;

&lt;p&gt;Distributes requests evenly across all servers.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; APIs with similar server capacities.&lt;br&gt;
&lt;strong&gt;Nginx illustration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream backend {
    server api1.example.com;
    server api2.example.com;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Least Connections (Great for Heavy Requests)
&lt;/h3&gt;

&lt;p&gt;Sends traffic to the server with the fewest active connections.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; APIs with &lt;strong&gt;long-running&lt;/strong&gt; or &lt;strong&gt;high-latency&lt;/strong&gt; requests.&lt;br&gt;
&lt;strong&gt;Nginx illustration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream backend {
    least_conn;
    server api1.example.com;
    server api2.example.com;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. IP Hash (Good for Session Persistence)
&lt;/h3&gt;

&lt;p&gt;Assigns each client’s request to the &lt;strong&gt;same server&lt;/strong&gt; based on their IP.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; APIs that need &lt;strong&gt;session consistency&lt;/strong&gt; (e.g. authentication, sticky sessions).&lt;br&gt;
&lt;strong&gt;Nginx illustration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream backend {
    ip_hash;
    server api1.example.com;
    server api2.example.com;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Weighted Load Balancing (Fine-Tuned Traffic Control)
&lt;/h3&gt;

&lt;p&gt;Some servers are &lt;strong&gt;more powerful than others&lt;/strong&gt;—this method &lt;strong&gt;sends more traffic to stronger servers.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; APIs running on mixed-capacity servers.&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream backend {
    server api1.example.com weight=3;
    server api2.example.com weight=1;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://api1.example.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;api1.example.com&lt;/strong&gt;&lt;/a&gt; gets &lt;strong&gt;3x more traffic&lt;/strong&gt; than &lt;a href="http://api2.example.com/" rel="noopener noreferrer"&gt;api2.example.com&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Real-World Case Study: PayU
&lt;/h2&gt;

&lt;p&gt;PayU one of India's leading payments and fintech companies *&lt;em&gt;serves over 450,000 merchants using over 100+ payment methods *&lt;/em&gt; and cannot afford API slowdowns. PayU uses application load balancers to scale their service 10x to meet demands during peak periods.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Common Load Balancing Issues &amp;amp; Fixes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Some servers get more traffic than others&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;strong&gt;Least Connections&lt;/strong&gt; instead of Round-Robin.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;High latency even with load balancing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enable &lt;strong&gt;Geo-DNS&lt;/strong&gt; to route users to nearby servers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Users randomly get logged out&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;strong&gt;session persistence&lt;/strong&gt; (sticky sessions).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unhealthy target servers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Implement &lt;strong&gt;health checks&lt;/strong&gt; and use &lt;strong&gt;auto scaling groups&lt;/strong&gt; to ensure new servers are spin up when one or more servers becomes unhealthy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. Best Practices for Load Balancing APIs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Choose the right strategy&lt;/strong&gt; – Round Robin is simple, but Least Connections or Weighted Load Balancing may be better.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Enable health checks&lt;/strong&gt; – Automatically remove failing servers from the pool.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Use cache alongside load balancing&lt;/strong&gt; – Combining both boosts performance further.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Monitor and tweak&lt;/strong&gt; – Use tools like Prometheus &amp;amp; Grafana to track load balancer health.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Conclusion &amp;amp; Resources
&lt;/h2&gt;

&lt;p&gt;Load balancing is &lt;strong&gt;essential for scaling APIs&lt;/strong&gt; and ensuring high availability. Whether you’re handling a small SaaS app or a global platform like &lt;strong&gt;PayU&lt;/strong&gt;, the right load balancing strategy &lt;strong&gt;prevents slowdowns, reduces costs, and improves user experience.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Continue with the 3rd part of this series Asynchronous Processing &amp;amp; Queues &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-3-asynchronous-processing-queues-h1d"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ibm.com/think/topics/load-balancing" rel="noopener noreferrer"&gt;https://www.ibm.com/think/topics/load-balancing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/elasticloadbalancing/application-load-balancer" rel="noopener noreferrer"&gt;https://aws.amazon.com/elasticloadbalancing/application-load-balancer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.appviewx.com/education-center/load-balancer-and-types/" rel="noopener noreferrer"&gt;https://www.appviewx.com/education-center/load-balancer-and-types/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-load-balancer" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-load-balancer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>programming</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Optimizing API Performance - Part 1: Caching</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Tue, 18 Mar 2025 10:42:02 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-1-caching-4fe4</link>
      <guid>https://forem.com/fredrick_oladipupo/optimizing-api-performance-part-1-caching-4fe4</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Why Caching Matters for API Performance&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ever waited too long for an app to load? &lt;strong&gt;Slow APIs frustrate users and cost businesses millions&lt;/strong&gt; in lost revenue. The good news? &lt;strong&gt;Caching can cut response times from seconds to milliseconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;APIs handle thousands (or even millions) of requests daily, often fetching the same data repeatedly. Speed is a value on its own and without caching, APIs  can suffer from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High database load&lt;/strong&gt; – Unnecessary queries for frequently accessed data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow API response times&lt;/strong&gt; – Every request has to process everything from scratch, boot your whole application and framework service providers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased infrastructure costs&lt;/strong&gt; – More server power needed to handle the same traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing caching, APIs can return precomputed responses instantly, &lt;strong&gt;reducing workload and boosting speed.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Types of Caching in APIs&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Client-Side Caching (Browser &amp;amp; Frontend Cache)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;APIs can instruct clients (browsers, mobile apps) to temporarily store data &lt;strong&gt;instead of refetching it repeatedly.&lt;/strong&gt; This is done via HTTP headers like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache-Control&lt;/strong&gt; – Defines how long the client should keep the response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETag (Entity Tag)&lt;/strong&gt; – Helps determine if data has changed before refetching.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Minimal Example: Client-Side Caching with Local Storage&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;popular_articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cachedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cachedData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/popular-articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Cache response&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cachedData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Use cached data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Case:&lt;/strong&gt; Reducing unnecessary API calls for static content like &lt;strong&gt;product details or user profiles.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Server-Side Caching (Memory-Based Cache)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of querying the database every time, APIs can &lt;strong&gt;store frequently requested data in-memory&lt;/strong&gt; using Redis or Memcached or Memory based cache of your choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Minimal Example: Server-Side Caching with Redis (Node.js)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/popular-articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;popular_articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Return cached response&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPopularArticlesFromDB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;popular_articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Cache for 1 hour&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caching &lt;strong&gt;user authentication sessions&lt;/strong&gt; to reduce database lookups.&lt;/li&gt;
&lt;li&gt;Storing &lt;strong&gt;popular API responses&lt;/strong&gt; (e.g., trending articles, weather forecasts).&lt;/li&gt;
&lt;li&gt;Reducing &lt;strong&gt;third-party API calls&lt;/strong&gt; by storing results instead of re-fetching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 &lt;strong&gt;Real-World Example:&lt;/strong&gt; Twitter caches user timelines in Redis to &lt;strong&gt;reduce database queries by 95%&lt;/strong&gt; while keeping user feeds responsive.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Database Query Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of executing expensive SQL queries every time, APIs can &lt;strong&gt;cache query results in memory.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Minimal Example: MySQL Query Caching with Redis (PHP)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$cacheKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"exchange_rates"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$cachedRates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$redis&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cacheKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$cachedRates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SELECT * FROM exchange_rates"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$rates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fetchAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$redis&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rates&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Cache for 1 hour&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$rates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cachedRates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache &lt;strong&gt;frequently accessed but rarely changing data&lt;/strong&gt; (e.g., country lists, exchange rates).&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;expiration times&lt;/strong&gt; (e.g., 1 hour) to prevent serving stale data.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;cache invalidation&lt;/strong&gt; to refresh data when updates occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Case:&lt;/strong&gt; An e-commerce platform caching &lt;strong&gt;product categories&lt;/strong&gt; to avoid &lt;strong&gt;database overload.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4. Full-Page Caching (Reverse Proxy Caching)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For read-heavy traffic, solutions like &lt;strong&gt;Varnish, Nginx, or Cloudflare&lt;/strong&gt; can cache entire API responses and serve them instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Minimal Example: Reverse Proxy Caching with Nginx&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location /api/ {
    proxy_pass http://backend_server;
    proxy_cache my_cache;
    proxy_cache_valid 200 1h;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Real-World Example:&lt;/strong&gt; A news API used &lt;strong&gt;Cloudflare's cache&lt;/strong&gt; to serve headlines, cutting response times from &lt;strong&gt;300ms to under 50ms globally.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;When Not to Use Caching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While caching is powerful, &lt;strong&gt;it’s not a silver bullet.&lt;/strong&gt; Avoid caching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Highly dynamic data&lt;/strong&gt; (e.g., real-time stock prices, chat messages, frequently changing data, financial data - wallet balance, transaction history).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;User-specific content&lt;/strong&gt; unless using per-user cache keys.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Data that must always be fresh&lt;/strong&gt; (e.g., real-time analytics, transaction records).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices for Implementing API Caching&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Cache strategically&lt;/strong&gt; – Not everything should be cached.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Set expiration policies&lt;/strong&gt; – Define how long data stays cached before refreshing.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Handle cache invalidation&lt;/strong&gt; – Clear outdated data when updates occur.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Monitor cache hit rates&lt;/strong&gt; – Track performance to ensure caching is effective.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  -  &lt;strong&gt;Use multiple cache layers&lt;/strong&gt; – Combine client-side, memory-based, and database caching for maximum speed.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Caching isn’t just an optimization—it’s a necessity for scaling APIs. Whether you’re building a small app or a global platform, &lt;strong&gt;smart caching can make the difference&lt;/strong&gt; between an API that struggles and one that scales.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Resources&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/cd/E19528-01/820-1652/adyml/index.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/cd/E19528-01/820-1652/adyml/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/elasticache" rel="noopener noreferrer"&gt;https://aws.amazon.com/elasticache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ibm.com/docs/en/was-nd/8.5.5?topic=caching-overview-proxy-server" rel="noopener noreferrer"&gt;https://www.ibm.com/docs/en/was-nd/8.5.5?topic=caching-overview-proxy-server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀 &lt;strong&gt;Next up in the API Performance Series: Load Balancing read &lt;a href="https://dev.to/fredrick_oladipupo/optimizing-api-performance-part-2-load-balancing-3ie5"&gt;here&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you used caching in your projects? What worked (or failed)? Let’s discuss in the comments!&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>caching</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Amazon S3 Security in Enterprise Applications: A Comprehensive Guide with Case Studies</title>
      <dc:creator>Fredrick Oladipupo</dc:creator>
      <pubDate>Sat, 15 Mar 2025 16:15:20 +0000</pubDate>
      <link>https://forem.com/fredrick_oladipupo/amazon-s3-security-in-enterprise-applications-a-comprehensive-guide-with-case-studies-1pjg</link>
      <guid>https://forem.com/fredrick_oladipupo/amazon-s3-security-in-enterprise-applications-a-comprehensive-guide-with-case-studies-1pjg</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction: Why S3 Security Matters for Enterprises&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Amazon S3 is one of the most widely used cloud storage solutions, handling data for businesses across industries like &lt;strong&gt;finance, healthcare, and e-commerce&lt;/strong&gt;. However, misconfigured S3 buckets have been responsible for some of the &lt;strong&gt;biggest data breaches&lt;/strong&gt; in history. In the last 10 years there has been &lt;a href="https://github.com/nagwww/s3-leaks" rel="noopener noreferrer"&gt;at least 20 data leaks from S3 due to bucket&lt;/a&gt; misconfigurations.&lt;/p&gt;

&lt;p&gt;For enterprises, &lt;strong&gt;data security is not optional&lt;/strong&gt;—it is essential for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Regulatory Compliance&lt;/strong&gt; (GDPR, HIPAA, PCI-DSS, CCPA)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Preventing Data Leaks&lt;/strong&gt; that damage trust and cause financial losses&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Protecting Against Ransomware &amp;amp; Insider Threats&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Ensuring Business Continuity&lt;/strong&gt; during regional outages or cyberattacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide walks through &lt;strong&gt;essential Amazon S3 security best practices&lt;/strong&gt;, backed by &lt;strong&gt;real-world case studies&lt;/strong&gt; to illustrate what can go wrong when these measures aren’t followed.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. S3 Block Public Access: Preventing Unauthorized Exposure&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why It’s Important&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the biggest mistakes companies make is leaving S3 buckets &lt;strong&gt;publicly accessible&lt;/strong&gt;. This can lead to &lt;strong&gt;data leaks, compliance violations, and security breaches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;AWS provides a &lt;strong&gt;Block Public Access&lt;/strong&gt; feature that allows organizations to &lt;strong&gt;centrally prevent public access at both the account and bucket level&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable S3 Block Public Access at the account level&lt;/strong&gt; to prevent any bucket from being made public, even by mistake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use IAM policies and bucket policies&lt;/strong&gt; to enforce strict access controls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor with AWS Config Rules&lt;/strong&gt; to flag publicly accessible buckets.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
CopyEdit
aws s3api put-public-access-block &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-secure-bucket &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--public-access-block-configuration&lt;/span&gt; &lt;span class="nv"&gt;BlockPublicAcls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;,IgnorePublicAcls&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;,BlockPublicPolicy&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;,RestrictPublicBuckets&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Case Study: The Public S3 Bucket Disaster&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;On October 3rd, 2017, UpGuard Director of Cyber Risk Research Chris Vickery discovered an Amazon Web Services S3 cloud storage bucket &lt;strong&gt;configured for public access, allowing any web user entering the repository’s URL to access and download the bucket’s contents&lt;/strong&gt;. The bucket’s subdomain, “crm-mvp,” likely refers to “customer record management” or “customer relationship management,” theories seemingly corroborated by the repository’s contents: &lt;strong&gt;forty-seven thousand files, most of them PDF and text documents, containing the sensitive information of National Credit Federation customers&lt;/strong&gt;. Read full security report &lt;a href="https://www.upguard.com/breaches/credit-crunch-national-credit-federation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Lesson Learned:&lt;/strong&gt; Always &lt;strong&gt;block public access by default&lt;/strong&gt; and enforce &lt;strong&gt;strict IAM policies&lt;/strong&gt; to avoid accidental exposure.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. S3 Object Lock: Preventing Accidental and Malicious Deletion&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why It’s Important&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Without proper safeguards, &lt;strong&gt;accidental deletions&lt;/strong&gt; or &lt;strong&gt;ransomware attacks&lt;/strong&gt; can wipe out critical data. &lt;strong&gt;S3 Object Lock&lt;/strong&gt;helps by &lt;strong&gt;preventing deletion or modification&lt;/strong&gt; of objects for a specified retention period.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable S3 Object Lock&lt;/strong&gt; for critical compliance data and audit logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Governance Mode&lt;/strong&gt; (admins can override) or &lt;strong&gt;Compliance Mode&lt;/strong&gt; (data is fully locked).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine Object Lock with Versioning&lt;/strong&gt; for stronger data protection.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
CopyEdit
aws s3api put-object-retention &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-secure-bucket &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key&lt;/span&gt; audit-logs.json &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--retention-mode&lt;/span&gt; COMPLIANCE &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--retain-until-date&lt;/span&gt; 2030-01-01T00:00:00Z

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Case Study: The Ransomware Attack on Cloud Backups&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;financial services company&lt;/strong&gt; stored audit logs in S3 but &lt;strong&gt;failed to enable Object Lock&lt;/strong&gt;. Hackers gained access and &lt;strong&gt;deleted all logs&lt;/strong&gt;, erasing valuable compliance records.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;Lesson Learned:&lt;/strong&gt; Use &lt;strong&gt;Object Lock with Compliance Mode&lt;/strong&gt; to &lt;strong&gt;prevent data loss from cyberattacks or human errors&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. S3 Versioning: Protecting Against Data Loss&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why It’s Important&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Even with the best security policies, human errors happen. &lt;strong&gt;S3 Versioning ensures you can recover previous versions&lt;/strong&gt; of an object in case of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accidental deletions or overwrites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application bugs&lt;/strong&gt; corrupting stored data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security incidents like insider threats&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable Versioning&lt;/strong&gt; on all critical S3 buckets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Lifecycle Policies&lt;/strong&gt; to delete older versions automatically and save storage costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine with MFA Delete&lt;/strong&gt; to prevent unauthorized deletions.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
CopyEdit
aws s3api put-bucket-versioning &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-secure-bucket &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--versioning-configuration&lt;/span&gt; &lt;span class="nv"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Enabled

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Case Study: The Insider Threat – Accidental Data Deletion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;healthcare organization&lt;/strong&gt; accidentally deleted a large dataset during maintenance. Because &lt;strong&gt;Versioning was disabled&lt;/strong&gt;, the data was &lt;strong&gt;lost permanently&lt;/strong&gt;, causing compliance violations.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;Lesson Learned:&lt;/strong&gt; Always &lt;strong&gt;enable S3 Versioning&lt;/strong&gt; to &lt;strong&gt;recover from accidental deletions or malicious activities&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Encryption: Ensuring Data Security at Rest and in Transit&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why It’s Important&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Regulatory bodies like &lt;strong&gt;GDPR, HIPAA, and PCI-DSS&lt;/strong&gt; require &lt;strong&gt;data encryption&lt;/strong&gt; to protect sensitive information.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Default S3 Encryption (SSE-S3)&lt;/strong&gt; to ensure all stored data is encrypted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage SSE-KMS for tighter control&lt;/strong&gt; using AWS Key Management Service (KMS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce encryption policies&lt;/strong&gt; with &lt;strong&gt;AWS Service Control Policies (SCPs)&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
CopyEdit
aws s3api put-bucket-encryption &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-secure-bucket &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--server-side-encryption-configuration&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s1"&gt;'{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Case Study: The Compliance Violation – Unencrypted Data Breach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;company storing customer PII&lt;/strong&gt; in S3 failed a &lt;strong&gt;GDPR audit&lt;/strong&gt; because their data &lt;strong&gt;wasn’t encrypted&lt;/strong&gt;. This led to a &lt;strong&gt;hefty fine&lt;/strong&gt; and loss of customer trust.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;Lesson Learned:&lt;/strong&gt; Always &lt;strong&gt;encrypt data at rest&lt;/strong&gt; using &lt;strong&gt;SSE-S3 or KMS&lt;/strong&gt; to meet compliance and security standards.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. S3 Cross-Region Replication: Disaster Recovery &amp;amp; High Availability&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why It’s Important&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Relying on a &lt;strong&gt;single AWS region&lt;/strong&gt; creates a &lt;strong&gt;single point of failure&lt;/strong&gt;. If a region goes down, &lt;strong&gt;your entire system could become unavailable&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable Cross-Region Replication (CRR)&lt;/strong&gt; to store redundant copies of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Lifecycle Policies&lt;/strong&gt; to automatically archive older data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replicate to a different AWS account&lt;/strong&gt; for additional security.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
CopyEdit
aws s3api put-replication-configuration &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-secure-bucket &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--replication-configuration&lt;/span&gt; file://replication.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Case Study: The Regional Outage – Data Loss Without Redundancy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;retail company&lt;/strong&gt; stored all its product catalog data in a &lt;strong&gt;single AWS region&lt;/strong&gt;. When that region suffered an &lt;strong&gt;extended outage&lt;/strong&gt;, they lost access to critical data, affecting sales and operations.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;Lesson Learned:&lt;/strong&gt; &lt;strong&gt;Always replicate critical data&lt;/strong&gt; across multiple AWS regions for disaster recovery.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Building a Secure S3 Strategy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Securing Amazon S3 requires a &lt;strong&gt;multi-layered approach&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;Block Public Access&lt;/strong&gt; – Prevents unauthorized exposure.&lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;Object Lock &amp;amp; Versioning&lt;/strong&gt; – Protects against deletions.&lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;Encryption&lt;/strong&gt; – Ensures compliance and secures data.&lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;Replication&lt;/strong&gt; – Improves resilience against failures.&lt;/p&gt;

&lt;p&gt;✔ &lt;strong&gt;IAM Policies &amp;amp; Access Controls&lt;/strong&gt; – Restricts data access.&lt;/p&gt;

&lt;p&gt;By learning from &lt;strong&gt;real-world security failures&lt;/strong&gt;, enterprises can &lt;strong&gt;fortify their cloud storage&lt;/strong&gt; against breaches, compliance risks, and disasters.&lt;/p&gt;

&lt;p&gt;Have you experienced S3 data leaks before, How did you handle it?&lt;br&gt;
What other security practices do you use in securing your data in S3 buckets? Let’s talk in the comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
