<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Anant Chowdhary - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Anant Chowdhary - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:29:51 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/anantchowdhary/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Message Queues Help Make Distributed Systems More Reliable ]]>
                </title>
                <description>
                    <![CDATA[ Reliable systems consistently perform their intended functions under various conditions while minimizing downtime and failures. As internet users, we tend to take for granted that the systems that we use daily will operate reliably. In this article, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-message-queues-make-distributed-systems-more-reliable/</link>
                <guid isPermaLink="false">671f94819cd90a859ae00b55</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AWS SQS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ distributed system ]]>
                    </category>
                
                    <category>
                        <![CDATA[ message queue ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anant Chowdhary ]]>
                </dc:creator>
                <pubDate>Mon, 28 Oct 2024 13:41:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729895479626/5d476c5d-9749-4c2a-977b-bcdd8b2b8199.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Reliable systems consistently perform their intended functions under various conditions while minimizing downtime and failures.</p>
<p>As internet users, we tend to take for granted that the systems that we use daily will operate reliably. In this article, we’ll explore how message queues enhance flexibility and fault tolerance. We’ll also discuss some challenges that we may face while using them.</p>
<p>After reading through, you’ll know how to implement reliable systems and what key performance factors to keep in mind.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>Before diving into this article, you should have a foundational understanding of cloud computing. Here are the key concepts:</p>
<ol>
<li><p>Basic principles of Cloud Computing</p>
</li>
<li><p>Availability in Distributed Systems</p>
</li>
<li><p>An understanding of the CAP theorem.</p>
</li>
</ol>
<h3 id="heading-table-of-contents"><strong>Table of Contents</strong></h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-does-reliability-mean-in-the-context-of-distributed-systems">Reliability in Distributed Systems</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-makes-software-reliable">What Makes Software Reliable?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-message-queue">What is a Message Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-message-queues-help-make-distributed-systems-more-reliable">How Message Queues Help Make Distributed Systems More Reliable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-challenges-with-message-queues">Challenges with Message Queues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ol>
<h2 id="heading-what-does-reliability-mean-in-the-context-of-distributed-systems"><strong>What Does Reliability Mean in the Context of Distributed Systems?</strong></h2>
<p>Reliability, according to the OED, is “the quality of being trustworthy or of performing consistently well”. We can translate this definition to the following in the context of distributed systems:</p>
<ol>
<li><p>The ability of a technological system, device, or component to consistently and dependably perform its intended functions under various conditions over time. For instance, in the context of online banking, reliability refers to the consistent and secure processing of transactions. Users expect to complete transfers and access their accounts without errors or outages.</p>
</li>
<li><p>The system being resilient to unexpected or erroneous interactions by users / other systems interacting with it. For instance, if a user tries to access a deleted file on a cloud storage system, the system can gracefully notify them and suggest alternatives, rather than crashing.</p>
</li>
<li><p>The system performs satisfactorily under its expected conditions of operation, as well as in the case of unexpected load and/or disruptions. An example of this is a video streaming service during a major sporting event. The system is designed to perform well under normal traffic but must also handle sudden spikes in users when a popular game starts</p>
</li>
</ol>
<p>This is quite a general view of what reliability is, and the definition changes with time, as systems change with changing technology.</p>
<h2 id="heading-what-makes-software-reliable"><strong>What Makes Software Reliable?</strong></h2>
<p>There are various key components that are used industry wide to make distributed software reliable as used across large scale systems.</p>
<h3 id="heading-data-replication"><strong>Data Replication</strong></h3>
<p>Data replication is a fundamental concept in system design where data is intentionally duplicated and stored in multiple locations or servers.</p>
<p>This redundancy serves several critical purposes, including enhancing data availability, improving fault tolerance, and enabling load balancing.</p>
<p>By replicating data across different nodes or data centers, we may be able to ensure that, in the event of a hardware failure or network issue, the data remains accessible. This reduces downtime and enhances system reliability.</p>
<p>It's essential to implement replication strategies carefully, considering factors like consistency, synchronization, and conflict resolution to maintain data integrity and reliability in distributed systems.</p>
<p>Let’s look at a concrete example. With a primary-secondary database model such as one used with e-commerce websites, we may have the following:</p>
<ol>
<li><p>Replication: The primary database handles all the write operations, whereas the secondary database(s) handles all the reads. This ensures that reads are spread out across multiple databases, enhancing performance and lowering the probability of a crash.</p>
</li>
<li><p>Consistency: The system may use eventual consistency to maintain integrity, ensuring that all replicas eventually reflect the same data. But during high-traffic periods, the website may temporarily allow for slight inconsistencies, such as showing outdated inventory levels.</p>
</li>
<li><p>Conflict Resolution: If two users attempt to buy a single available item at the same time, a conflict resolution strategy may be used. For instance, the system could use timestamps to determine the customer who gets assigned the product, and this may dictate database updates eventually.</p>
</li>
</ol>
<h3 id="heading-load-distribution-across-machines"><strong>Load Distribution Across Machines</strong></h3>
<p>Load distribution involves distributing computational tasks and network traffic across multiple servers or resources to optimize performance and ensure system scalability.</p>
<p>By intelligently spreading workloads, load distribution prevents any single server from becoming overwhelmed, reducing the risk of bottlenecks and downtime.</p>
<p>Some very commonly used load distribution mechanisms are:</p>
<ol>
<li><p>Using Load Balancers: A load balancer can evenly distribute incoming traffic across multiple servers, preventing any single server from becoming a bottleneck.</p>
</li>
<li><p>Dynamic Scaling: Dynamic or auto-scaling can be used to automatically adjust the number of active servers based on current demand, adding more resources during peak times and scaling down during low traffic.</p>
</li>
<li><p>Caching: Caching layers can be used to store frequently accessed data, reducing the load on backend servers by serving requests directly from the cache.</p>
</li>
</ol>
<h3 id="heading-capacity-planning"><strong>Capacity Planning</strong></h3>
<p>Capacity planning entails analyzing factors such as expected user growth, data storage requirements, and processing capabilities to ensure that the system can handle increased loads without performance degradation or downtime.</p>
<p>By accurately forecasting resource needs and scaling infrastructure accordingly, such planning helps optimize costs, maintain reliability, and provide a seamless user experience. Being proactive can help ensure a system is well-prepared to adapt to changing requirements and remains robust and efficient throughout its lifecycle.</p>
<p>A lot of modern systems can scale automatically with projected loads. When traffic or processing requirements increase, such auto scaling automatically provisions additional resources to handle the load. Conversely, when demand decreases, it scales down resources to optimize cost efficiency.</p>
<h3 id="heading-metrics-and-automated-alerting"><strong>Metrics and Automated Alerting</strong></h3>
<p>Metrics involve collecting and analyzing data points that provide insights into various aspects of system behavior, such as resource utilization, response times, error rates, and more.</p>
<p>Automated alerting complements metrics by enabling proactive monitoring. This involves setting predefined thresholds or conditions based on metrics. When a metric crosses or exceeds these thresholds, automated alerts get triggered. These alerts can notify system administrators or operators, allowing them to take immediate action to address potential issues before they impact the system or users.</p>
<p>When used together, metrics and automated alerting create a robust monitoring and troubleshooting system, helping ensure that anomalies or problems are quickly detected and resolved.</p>
<p>Now that you know a bit about what reliability means in the context of Distributed Systems, we can move on to Message Queues.</p>
<h2 id="heading-what-is-a-message-queue"><strong>What is a Message Queue?</strong></h2>
<p>A message queue is a communication mechanism used in distributed systems to enable asynchronous communication between different components or services. It acts as an intermediary that allows one component to send a message to another without the need for direct, synchronous communication.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1701696280571/8697cb07-c765-4f9e-b709-a7a03adf3e11.png?auto=compress,format&amp;format=webp" alt="Multiple producers adding messages to a message queue that in turn are consumed by a consumer." class="image--center mx-auto" width="480" height="370" loading="lazy"></p>
<p>Above, you can see that there are multiple nodes (called Producers) that create messages that are sent to a message queue. These messages are processed by a node called the Consumer node, which may perform a series of actions (for instance database reads, or writes) as a part of each message being processed.</p>
<p>Now let’s look at an actual example where a message queue may be useful. Let’s assume we have an e-commerce website that allows millions of orders to be processed.</p>
<p>Processing an order may take place in the following steps:</p>
<ol>
<li><p>A user creates an order. This sets off a request to a web server, that in turn creates a message that is placed in the orders queue.</p>
</li>
<li><p>A consumer reads the message, and in turn calls different services while processing the message (for instance the inventory checks, the payment service, the shipping service)</p>
</li>
<li><p>Once all processing steps have completed, the consumer removes the message from the queue.</p>
</li>
</ol>
<p>Note that in case there are parts of the system that fail, the message can be left in the queue to be re-processed.</p>
<p>Even in cases where there is a total outage on the processing side of things, messages can simply pile up in the queue and be consumed once services are functional again. This is an example of a queue being useful in multiple failure scenarios.</p>
<p>Let’s look at some code for this scenario using AWS SQS, which is a popular message queue service that allows users to create queues, send messages to the queue, and also consume messages from queues for processing.</p>
<p>The below example uses <a target="_blank" href="http://boto3.amazonaws.com">Boto3</a> which is a Python Client for AWS SQS.</p>
<p>First, we’ll place an order, assuming we already have an SQS queue called OrderQueue in place.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Create an SQS client</span>
sqs = boto3.client(<span class="hljs-string">'sqs'</span>)

<span class="hljs-comment"># Let's assume the queue is called OrderQueue</span>
<span class="hljs-comment"># This is the queue in which orders are placed</span>
queue_url = <span class="hljs-string">'https://sqs.us-east-1.amazonaws.com/2233334/OrderQueue'</span>

<span class="hljs-comment"># Function to send an order message</span>
<span class="hljs-comment"># This places an order in the queue, which can at any time be</span>
<span class="hljs-comment"># picked up by a consumer and then processed</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_order</span>(<span class="hljs-params">order_details</span>):</span>
    message_body = json.dumps(order_details)
    response = sqs.send_message(
        QueueUrl=queue_url,
        MessageBody=message_body
    )
    print(<span class="hljs-string">f'Order sent with ID: <span class="hljs-subst">{response[<span class="hljs-string">"MessageId"</span>]}</span>'</span>)

<span class="hljs-comment"># Using the queue to place an order</span>
<span class="hljs-comment"># Defining a sample order</span>

order = {
    <span class="hljs-string">'order_id'</span>: <span class="hljs-string">'12345'</span>,
    <span class="hljs-string">'customer_id'</span>: <span class="hljs-string">'67890'</span>,
    <span class="hljs-string">'items'</span>: [
        {<span class="hljs-string">'product_id'</span>: <span class="hljs-string">'abc123'</span>, <span class="hljs-string">'quantity'</span>: <span class="hljs-number">2</span>},
        {<span class="hljs-string">'product_id'</span>: <span class="hljs-string">'xyz456'</span>, <span class="hljs-string">'quantity'</span>: <span class="hljs-number">1</span>}
    ],
    <span class="hljs-string">'total_price'</span>: <span class="hljs-number">59.99</span>
}

<span class="hljs-comment"># Sending the order to the queue which is expected to be picked up </span>
<span class="hljs-comment"># by a consumer and processed eventually.</span>
send_order(order)
</code></pre>
<p>Then once the order has been placed, here’s some code that illustrates how it’ll be picked up for processing:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Create an SQS client</span>
sqs = boto3.client(<span class="hljs-string">'sqs'</span>)

<span class="hljs-comment"># Processing orders from the same queue defined above</span>
queue_url = <span class="hljs-string">'https://sqs.us-east-1.amazonaws.com/2233334/OrderQueue'</span>

<span class="hljs-comment"># Function to receive and process orders</span>
<span class="hljs-comment"># Picking up a maximum of 10 messages at a time to process</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive_orders</span>():</span>
    response = sqs.receive_message(
        QueueUrl=queue_url,
        MaxNumberOfMessages=<span class="hljs-number">10</span>,  <span class="hljs-comment"># Up to 10 messages</span>
        WaitTimeSeconds=<span class="hljs-number">10</span>
    )

    messages = response.get(<span class="hljs-string">'Messages'</span>, [])

    <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> messages:
        order_details = json.loads(message[<span class="hljs-string">'Body'</span>])
        print(<span class="hljs-string">f'Processing order: <span class="hljs-subst">{order_details}</span>'</span>)

        <span class="hljs-comment"># Processing the order with details such as </span>
        <span class="hljs-comment"># processing payments, updating the inventory levels,</span>
        <span class="hljs-comment"># processing shipping etc.</span>

        <span class="hljs-comment"># Delete the message after processing</span>
        <span class="hljs-comment"># This is important since we don't want an</span>
        <span class="hljs-comment"># order to be processed multiple times.</span>
        sqs.delete_message(
            QueueUrl=queue_url,
            ReceiptHandle=message[<span class="hljs-string">'ReceiptHandle'</span>]
        )

<span class="hljs-comment"># Receive a batch of orders</span>
receive_orders()
</code></pre>
<h3 id="heading-what-is-an-intermediary-in-a-distributed-system"><strong>What is an Intermediary in a Distributed System?</strong></h3>
<p>In the context of what we’re discussing here, a message queue is an intermediary. Quoting Amazon AWS’ definition of a message queue:</p>
<blockquote>
<p>“<a target="_blank" href="https://aws.amazon.com/sqs/"><strong><em>Amazon Simple Queue Service (Amazon SQS)</em></strong></a> <em>lets you send, store, and receive messages between software components at any volume, without losing messages or requiring other services to be available</em>.”</p>
</blockquote>
<p>This is a wonderfully succinct and accurate description of why a message queue (an intermediary) is important.</p>
<p>In a message queue, messages are placed in a queue data structure, which you can think of as a temporary storage area. The producer places messages in the queue, and the consumer retrieves and processes them at its own pace. This decoupling of producers and consumers allows for greater flexibility, scalability, and fault tolerance in distributed systems.</p>
<h2 id="heading-how-message-queues-help-make-distributed-systems-more-reliable">How Message Queues Help Make Distributed Systems More Reliable</h2>
<p>Now let's discuss how Message Queues help make Distributed Systems more reliable.</p>
<h3 id="heading-1-message-queues-provide-flexibility"><strong>1. Message Queues Provide Flexibility</strong></h3>
<p>Message queues allow for <a target="_blank" href="https://en.wikipedia.org/wiki/Asynchrony_\(computer_programming\)"><strong>asynchronous communication</strong></a> between components. This means that producers can send messages to the queue without waiting for immediate processing by consumers. This allows components to work independently and at their own pace, providing flexibility in terms of processing times. So this is a great way to make designs flexible, and as self contained as possible.</p>
<h3 id="heading-2-message-queues-make-systems-scalable"><strong>2. Message Queues Make Systems Scalable</strong></h3>
<p>Message queues are often the bread and butter of scalable distributed systems for the following reasons:</p>
<ol>
<li><p>Multiple producers can add messages to a message queue. This raises the ceiling and allows us to easily horizontally scale applications.</p>
</li>
<li><p>Multiple consumers can read from a message queue. This again allows us to easily scale throughput if needed in a lot of scenarios.</p>
</li>
</ol>
<h3 id="heading-3-message-queues-make-systems-fault-tolerant"><strong>3. Message Queues Make Systems Fault Tolerant</strong></h3>
<p>What happens if a distributed system is overwhelmed? We sometimes need to have the ability to <em>cut the cord</em> in order to get the system back to a working state. We’d ideally want the ability to process requests that weren’t processed when the system was down.</p>
<p>This is exactly what a message queue can help us with. We may have hundreds of thousands of requests that weren’t processed, but are still in the queue. These can be processed once our system is back online.</p>
<h2 id="heading-challenges-with-message-queues"><strong>Challenges with Message Queues</strong></h2>
<p>As with life, using message queues in distributed systems isn’t a silver bullet to scaling problems.</p>
<p>Here are some situations where message queues may be useful:</p>
<ol>
<li><p>Asynchronous Processing: Messages queues are generally an excellent choice in infrastructure wherever asynchronous processing is required. In workflows such as sending confirmation emails or generating reports after an order is placed, message queues can decouple these tasks from the primary application flow.</p>
</li>
<li><p>Load Balancing: As we saw in our example for message queues, in scenarios where traffic spikes occur, message queues can buffer incoming requests, allowing multiple consumers to process messages concurrently. This helps distribute the load evenly across available resources.</p>
</li>
<li><p>Fault Tolerance: In systems where reliability is crucial, message queues provide a mechanism for handling failures. If a service is temporarily down, messages can be retained in the queue until the service is available again, ensuring that no data is lost unless intended.</p>
</li>
</ol>
<p>Here are a some situations where message queues may not be useful:</p>
<ol>
<li><p>Message queues can be great in scenarios where ordering of messages does not matter. But in situations where order does matter, they can sometimes be slow and more expensive to use.</p>
</li>
<li><p>Designing systems with queues that have multiple consumers isn’t trivial. What happens if a message is processed twice? Is <a target="_blank" href="https://en.wikipedia.org/wiki/Idempotence"><strong>idempotency</strong></a> a requirement? Or does it break our use case? These complexities can often lead us to situations where message queues may not be the best solution.</p>
</li>
</ol>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>In this article, you learned about reliability in distributed systems, and how message queues can help make such systems more reliable. Here’s a summary of the key takeaways:</p>
<ol>
<li><p>Reliability is central to distributed systems and there are a few common ways this is handled across the tech industry. Data replication, load distribution, and capacity planning are some ways that can improve the reliability of a system.</p>
</li>
<li><p>Message Queues are intermediaries that can store messages from producers. They can be picked up by consumers at a rate that's generally independent of the rate of production.</p>
</li>
<li><p>Queues are flexible, allowing us to immediately stem the flow of unwanted event processing in case of an unforeseen event.</p>
</li>
<li><p>Despite the versatility of message queues, they're not a panacea for reliability issues. There are often multiple considerations to be kept in mind while processing messages in a message queue.</p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Time To Live in Event-Driven Architecture in AWS ]]>
                </title>
                <description>
                    <![CDATA[ Distributed systems generally involve the storage and exchange of huge amounts of data. Not all data is created the same, and some of it can even expire – by design.  As the Buddha said, "All conditioned things are impermanent." In this article, we'l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-time-to-live-in-event-driven-architecture/</link>
                <guid isPermaLink="false">66d03360537f4deb8f7a794f</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ distributed systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anant Chowdhary ]]>
                </dc:creator>
                <pubDate>Wed, 19 Jun 2024 18:08:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/pexels-giallo-859895.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Distributed systems generally involve the storage and exchange of huge amounts of data. Not all data is created the same, and some of it can even <em>expire</em> – by design. </p>
<p>As the Buddha said, "All conditioned things are impermanent."</p>
<p>In this article, we'll look at how the concept of time to live can help us with this type of data and when it makes sense to use it.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-time-to-live-ttl-in-distributed-systems">What is Time to Live (TTL) in Distributed Systems?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-ttl-in-message-queues-aws-sqs">How to use TTL in Message Queues (AWS SQS)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-ttl-in-object-storage-systems-aws-s3">How to use TTL in Object Storage Systems (AWS S3)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-ttl-in-databases-aws-dynamodb">How to use TTL in Databases (AWS DynamoDB)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-ttl-in-event-based-architecture">How to use TTL in Event Based Architecture</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ol>
<h2 id="heading-what-is-time-to-live-ttl-in-distributed-systems">What is Time to Live (TTL) in Distributed Systems?</h2>
<p>TTL, as the name suggests, is the amount of time a piece of data stays relevant or stays stored in a distributed system or a component of a distributed system. A TTL may be set on any piece of data that isn't needed indefinitely.</p>
<p>Knowing when and when not to use a TTL can sometimes be tricky. It can also affect the way a system is designed, cost and scaling considerations. In the following sections, we learn about when and when not to use TTL.</p>
<h3 id="heading-where-does-ttl-make-sense">Where does TTL make sense?</h3>
<p>As mentioned above, it makes sense to use TTL for any piece of data that is ephemeral. Some common examples of use cases where you can set a TTL on data are:</p>
<ol>
<li><strong>Cached data</strong>: Cached data is pretty much omnipresent in distributed systems. For instance, a very popular social media post's resources (image, video, audio) may be cached on a CDN (Content Delivery Network)'s servers. You don't want this data to live forever on the server, so in some cases it may make sense to add a TTL to this data, so that it is automatically removed after a certain period of time.</li>
<li><strong>Analytics Data</strong>: Most if not all large scale systems store some form of metrics that help analyze things like latency, system health, and product metrics amongst others. In a large number of cases, you wouldn't want these metrics to be stored in systems forever. Only recent data (say 60 days or 180 days) may be useful in most cases. A TTL on data in this case makes sense, especially if you have constraints on memory.</li>
<li><strong>Indexed data</strong>: Search is a feature that's ubiquitous across products. Be it social media apps, e-mail or search engines – indexed data is vital to blazing fast searches. Indexed data, however, can become stale after a while, so it makes sense for the index to <em>expire</em> after some time. Hence, a TTL here can be useful.</li>
<li><strong>Social media apps with short lived content:</strong> Social media apps with short lived content are extremely popular and images/videos posted are often short lived. In case these images do not need to be stored for posterity, they can benefit from a TTL being set on them. In addition to being memory efficient, it also aids privacy.</li>
</ol>
<h3 id="heading-where-does-ttl-not-make-sense">Where does TTL not make sense?</h3>
<p>In the above section we looked at a few cases where TTL makes sense. What about cases where TTL isn't common and isn't useful? Let's look at some examples:</p>
<ol>
<li><strong>Media stored for streaming platforms:</strong> Streaming platforms often use cloud storage solutions such as Amazon AWS S3 to store objects that correspond to the media they stream to customers. These forms of media are generally not ephemeral and are expected to stay on platforms for years if not decades. Since such data isn't expected to <em>expire</em> anytime, TTL does not make sense here.</li>
<li><strong>Bank transactions:</strong> Bank transactions produce some of the most sensitive data that are stored in cloud-based and distributed systems. For audit and book-keeping purposes, these pieces of data are generally stored for decades. So, since this data seemingly <em>never</em> expires, there's generally no use for a TTL here. This isn't to say that this form of data can't be moved from fast access databases/caches to slower and cheaper forms of data storage, though.</li>
</ol>
<h2 id="heading-how-to-use-ttl-in-message-queues-aws-sqs">How to Use TTL in Message Queues (AWS SQS)</h2>
<p>AWS SQS is a distributed message queuing solution that is the backbone of many versatile distributed systems across the world. Message queues can process billions of messages and are used almost universally across distributed systems around the world. </p>
<p>In this section, we'll look at how TTLs can be useful while we consider design options with respect to message queues.</p>
<p>What happens if a message queue's consumers have been backed up for several days, or messages simply haven't been consumed for a while? We have the option of setting a custom Time To Live on SQS messages.</p>
<p><a target="_blank" href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html#">By default, the retention period is 4 days</a>. The maximum TTL at the time of writing is 14 days. So it's important to be aware of constraints such as these while using AWS SQS to design systems.</p>
<p>Note that with AWS SQS, a retention period is a set on the queue itself, and not individually for each message.</p>
<p>Boto is an AWS SDK for Python that enables developers to create, configure, and manage AWS services and resources programmatically. Boto is widely used for prototyping, production systems, and in general offers a user-friendly interface for accessing services like S3, EC2, and DynamoDB.</p>
<p>Here's a code snippet using <a target="_blank" href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html">Boto</a> that will help you set the <code>MessageRetentionPeriod</code> attribute which is the formal name for TTL in this context.</p>
<pre><code class="lang-python">sqs = boto3.client(<span class="hljs-string">'sqs'</span>, 
aws_access_key_id=your_aws_access_key_id, 
aws_secret_access_key=aws_secret_access_key, 
region_name=<span class="hljs-string">'your_region'</span>)

<span class="hljs-comment"># Set the desired retention period in seconds</span>
retention_period_seconds = <span class="hljs-number">86400</span>  <span class="hljs-comment"># Example: 1 day</span>

<span class="hljs-comment"># Set the queue attributes</span>
response = sqs.set_queue_attributes(
    QueueUrl=your_queue_url,
    Attributes={
        <span class="hljs-string">'MessageRetentionPeriod'</span>: str(retention_period_seconds)
    }
)
</code></pre>
<h3 id="heading-visibility-timeout-in-message-queues-aws-sqs">Visibility Timeout in Message Queues (AWS SQS)</h3>
<p>Note that while it's tempting to think of <a target="_blank" href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html">Visibility Timeout in SQS</a> as Time To Live, these aren't the same. Time To Live or Retention Period is different from Visibility Timeout.</p>
<p>Visibility timeout instead refers to a generally shorter period of time by which a message should be processed (once picked up by a consumer). If not, it is back in the SQS queue and visible to consumers again, with its receive count having been increased by one.</p>
<h2 id="heading-how-to-use-ttl-in-object-storage-systems-aws-s3">How to Use TTL in Object Storage Systems (AWS S3)</h2>
<p>The all-versatile AWS S3, which is an object storage solution, gives users the ability to set a Time To Live on objects stored in S3 buckets.</p>
<p>S3 is extremely flexible with the way TTLs are set on objects / buckets. You can set Lifecycle rules to specify what objects or what versions of an object you'd like to remove.</p>
<p><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html">Managing your storage lifecycle</a> is a great read on the AWS Documentation website.</p>
<h2 id="heading-how-to-use-ttl-in-databases-aws-dynamodb">How to Use TTL in Databases (AWS DynamoDB)</h2>
<p>Some types of data in databases are prime candidates to have a TTL set on them. Pieces of data such as logs and analytics data may become stale very fast, and/or they may lose utility with time.</p>
<p>TTL in DynamoDB provides a cost-effective approach that lets you automatically remove items that are no longer relevant. It is supported natively and can be set on the whole DynamoDB table.</p>
<p>Here's a code snippet that lets you set the TTL on a DynamoDB table (again, using Boto):</p>
<pre><code class="lang-python">ddb_client = boto3.client(<span class="hljs-string">'dynamodb'</span>)

<span class="hljs-comment"># Enable Time To Live (TTL) on an existing DynamoDB table</span>
ttl_response = ddb_client.update_time_to_live(
    TableName=your_table_name,
    TimeToLiveSpecification={
        <span class="hljs-string">'Enabled'</span>: <span class="hljs-literal">True</span>,
        <span class="hljs-string">'AttributeName'</span>: your_ttl_attribute_name
    }
)

<span class="hljs-comment"># Check for a successful status code in the response</span>
<span class="hljs-keyword">if</span> ttl_response[<span class="hljs-string">'ResponseMetadata'</span>][<span class="hljs-string">'HTTPStatusCode'</span>] == <span class="hljs-number">200</span>:
    print(<span class="hljs-string">"Time To Live (TTL) has been successfully enabled."</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Failed to enable Time To Live (TTL)"</span>)
</code></pre>
<p>Here, the <code>your_ttl_attribute_name</code> attribute is the attribute that DynamoDB looks at to determine whether or not the item is to be deleted. The attribute is generally set to some timestamp in the future. When that timestamp is reached, DynamoDB removes the item from the table.</p>
<h2 id="heading-how-to-use-ttl-in-event-based-architecture">How to Use TTL in Event-Based Architecture</h2>
<p>So far we've discussed Time To Live and where it can be useful. What about its implications? Lots of cloud based solutions provide notifications that can indicate that a piece of data has indeed reached it's <em>expiration</em>, and allow you to take actions based on the expiration of that data.</p>
<p>Let's look at a common use case. Suppose you have a social media app that you're building that lets users send each other ephemeral messages. Now while the contents of these messages themselves are ephemeral, you may still want to retain a log of what users a particular user exchanged messages with, even though the contents of the message (audio/video/image) may have expired.</p>
<p>The diagram below explains a possible architecture in a little more detail:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706250152880/7c0d7b46-df5f-4d22-996f-4ea75889630e.png" alt="Image" width="591" height="381" loading="lazy">
<em>Social Media App Architecture Example</em></p>
<p>Suppose a user exchanges messages with another user. An entry corresponding to a message is stored in <em>ActiveMessageDB</em> which, for the purpose of simplicity, we'll suppose is a NoSQL database that stores messages.</p>
<p>If the app here allows for expiring messages, you could set a TTL on the entry. While the message entry itself is deleted after the TTL is reached, an event can be fired off to let a system know that the message is being deleted. </p>
<p>In the above diagram, the event is picked up by an AWS Lambda instance and a much smaller amount of data is written to another database <em>MessageLogDB</em> which isn't as frequently accessed as <em>ActiveMessageDB.</em> What we just saw is an instance of event-based architecture being coupled with TTL.</p>
<h2 id="heading-summary">Summary</h2>
<ol>
<li>TTL is the amount of time a piece of data stays relevant or stays stored in a distributed system or a component of a distributed system.</li>
<li>TTL makes sense in use cases where data can be deleted, can expire, or its form can change after a certain period of time.</li>
<li>TTL is popular and generally easy to set on many distributed systems offerings.</li>
<li>TTL can be paired with event driven architecture to transform data.</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deal with Traffic Surges in Distributed Systems ]]>
                </title>
                <description>
                    <![CDATA[ Web and Distributed Systems can often get overwhelmed with traffic.  What leads to systems being overwhelmed, why does it happen, and what are some common strategies we can use to deal with this? We'll answer these questions in this article. Table of... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deal-with-traffic-surges-in-distributed-systems/</link>
                <guid isPermaLink="false">66d0335ce5792f81c494c076</guid>
                
                    <category>
                        <![CDATA[ distributed systems ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anant Chowdhary ]]>
                </dc:creator>
                <pubDate>Fri, 17 May 2024 06:50:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/pexels-pixabay-327345.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Web and Distributed Systems can often get overwhelmed with traffic. </p>
<p>What leads to systems being overwhelmed, why does it happen, and what are some common strategies we can use to deal with this? We'll answer these questions in this article.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-traffic-in-the-context-of-distributed-systems">What is traffic in the context of distributed systems</a>?</li>
<li><a class="post-section-overview" href="#heading-why-can-traffic-surges-be-problematic">Why can traffic surges be problematic?</a> </li>
<li><a class="post-section-overview" href="#heading-ways-to-deal-with-high-traffic-loads">Ways to deal with high traffic loads</a></li>
<li><a class="post-section-overview" href="#heading-exponential-backoff-and-retries">Exponential Backoff and Retries</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ol>
<h2 id="heading-what-is-traffic-in-the-context-of-distributed-systems">What is Traffic in the Context of Distributed Systems?</h2>
<p>Traffic in distributed systems generally refers to the exchange of data between end users and the entry point to a system that may rely on distributed components. </p>
<p>The patterns of traffic a system sees usually informs multiple design decisions since it impacts performance, scalability and reliability of a system.</p>
<h2 id="heading-why-can-traffic-surges-be-problematic">Why Can Traffic Surges be Problematic?</h2>
<p>Traffic surges can often cripple systems that aren’t equipped to deal with them. </p>
<p>You may have come across instances of social media services such as Instagram or TikTok being down. In some cases, this may be due to surges of traffic.</p>
<p>Here are some common problems a surge in traffic may cause: </p>
<ol>
<li><strong>Congestion</strong>: As traffic increases, network congestion may increase. This may in some cases, lead to packet loss, increased latency and impact performance of systems. </li>
<li><strong>Imbalanced load</strong>: Not all distributed systems balance load well. A sudden spike in traffic may lead to failures in particular sub-systems. As an example, let’s think of a celebrity’s tweets being stored on a shard. In the scenario where an event leads to millions of people accessing the celebrity’s tweets, the shard that stores the celebrity’s tweets may get overwhelmed. </li>
<li><strong>Cascading failures</strong>: Imagine a set of domninoes that are placed right next to each other. One domino falling may lead to the entire set of dominoes falling. Distributed systems are similar. If components aren't loosely coupled, a single point of failure may lead to cascading failures. It is therefore important to consider cascading failures when designing distributed systems with high traffic loads in mind.</li>
</ol>
<h2 id="heading-ways-to-deal-with-high-traffic-loads">Ways to Deal with High Traffic Loads</h2>
<p>No system is immune to failure under an unspecified amount of traffic.</p>
<p>Fortunately, there are some design decisions you can take to ameliorate the problems discussed above, and make systems more resilient against failure when they see a sudden spike in traffic. </p>
<p>Now, let's cover some of the commonly used solutions that can help deal with surges in traffic.</p>
<p>Firstly, horizontal scaling is generally the process of adding resources to a system by adding more resources in parallel. For instance, adding more servers or adding more CDN nodes. </p>
<p>In effect, it is adding more resources instead of increasing the capacity of a single node in the network. </p>
<p>Distributing traffic across servers can lead to improved performance, lower latency, and improved response times in general.</p>
<p>Next, load balancing can sometimes be closely linked with horizontal scaling. However, load balancing by itself also can be very useful in situations where we see a sudden surge in traffic. </p>
<p>Load balancers can smartly route requests to servers so that traffic is well balanced across systems, and doesn't overwhelm one particular system.</p>
<p>In addition, caching can dramatically reduce the need for traffic (requests) to go all the way to a server for fulfilment.  Some types of requests, such as those that access static content as great candidates for caching. </p>
<p>Similar to an example that we discussed in the above sections, let's assume that there's a sudden spike in people viewing a celebrity's tweets. The static content on the page, such as the celebrity's display picture, can be easily cached. This will prevent a request that goes all the way to the profile picture database, and therefore may help prevent read failures, and in turn cascading failures. </p>
<p>Lastly, consider a scenario where a client internal to a distributed system sends a request to the server and the request fails. Clients often retry requests, but this may lead to cascading retries. </p>
<p>This is a scenario where multiple clients (the original one, and the one downstream) may be retrying their requests, and as a result, a system downstream may be inundated with requests and that by itself may lead to cascaded failures.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/CascadingRetries.drawio.png" alt="Image" width="600" height="400" loading="lazy">
<em>A single retry request can lead to an exponential number of retries in other parts of a distributed system</em></p>
<p>In the figure above, we can see that two requests from the server (one retry in the event of a failure at the Queue), leads to : </p>
<p>1) Four Requests from the serverless component to the Notification Topic (two requests to the serverless component and two retries)</p>
<p>2) Eight Requests from the Notification Topic to the Queue (four requests to the queue, four retries).</p>
<p>Even a single failure at the end component (the Queue in this case), led to an exponential number of retry requests to it.</p>
<p>A common antidote to this problem is to use exponential backoff while retrying requests.</p>
<h2 id="heading-exponential-backoff-and-retries">Exponential Backoff and Retries</h2>
<p>Exponential backoff, as the name suggests, refers to introducing a delay before the next attempt instead of immediately retrying. We increase the delay time exponentially with each attempt. </p>
<p>For instance, the first retry might wait for one second, the second retry waits for two seconds, the third for four seconds, and so on. </p>
<p>Note that since a retry attempt isn't made immediately, the probability of cascading retries goes down compared to if retries were made immediately.</p>
<p>Here's some code that illustrates exponential backoff in action : </p>
<pre><code class="lang-python">
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">exponential_backoff_retry</span>(<span class="hljs-params">url, max_retries=<span class="hljs-number">5</span>, initial_delay=<span class="hljs-number">1</span>, backoff_factor=<span class="hljs-number">2</span></span>):</span>
    retry_count = <span class="hljs-number">0</span>
    <span class="hljs-keyword">while</span> retry_count &lt; max_retries:
        <span class="hljs-keyword">try</span>:
            response = requests.get(url)
            <span class="hljs-comment"># Check if the response was successful (status code 2xx)</span>
            <span class="hljs-keyword">if</span> response.status_code // <span class="hljs-number">100</span> == <span class="hljs-number">2</span>:
                <span class="hljs-keyword">return</span> response
            <span class="hljs-comment"># If not successful, raise an exception to trigger a retry</span>
            response.raise_for_status()
        <span class="hljs-keyword">except</span> requests.exceptions.RequestException <span class="hljs-keyword">as</span> e:
            print(<span class="hljs-string">f"Request failed: <span class="hljs-subst">{e}</span>"</span>)
            <span class="hljs-comment"># Calculate the exponential backoff delay</span>
            delay = initial_delay * (backoff_factor ** retry_count)
            print(<span class="hljs-string">f"Retrying in <span class="hljs-subst">{delay}</span> seconds..."</span>)
            time.sleep(delay)
            retry_count += <span class="hljs-number">1</span>
    <span class="hljs-comment"># If max retries reached, raise an exception</span>
    <span class="hljs-keyword">raise</span> RuntimeError(<span class="hljs-string">f"Failed to fetch <span class="hljs-subst">{url}</span> after <span class="hljs-subst">{max_retries}</span> retries"</span>)
</code></pre>
<p>The code above retries HTTP GET requests using an exponential backoff strategy.</p>
<p>Inside the while loop, we make attempts to make the request and check if the response is successful (successful HTTP requests have a status code of 2xx). </p>
<p>Note that if the request fails, we raise an exception and retry the request after calculating an exponential delay. </p>
<p>This process is continued until either a request succeeds or the maximum number of retries is reached. If the maximum retries are exhausted without success, we raise a <code>RuntimeError</code>. </p>
<h2 id="heading-summary">Summary</h2>
<p>To summarize, we delved into the significance of traffic within distributed systems, emphasizing its influence on system performance and resilience. </p>
<p>We looked at the complications arising from traffic surges, including network congestion, load imbalances, and cascading failures, which can render systems vulnerable to collapse. </p>
<p>To address these challenges, we looked at some strategic measures such as horizontal scaling, load balancing, caching, and retry strategies. Particularly, we looked at the effectiveness of exponential backoff in mitigating cascading retries, thereby enhancing system robustness. </p>
<p>By keeping in mind some of these solutions, systems can better manage sudden spikes in traffic, ensuring sustained functionality and minimizing potential downtime, ultimately bolstering overall system reliability.</p>
<p>These are just a few of the numerous methods that are used industry wide to deal with surges in traffic.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Asynchronous vs Batch Data Processing in Distributed Systems – Explained with Examples ]]>
                </title>
                <description>
                    <![CDATA[ Distributed Systems often process and store huge amounts of data. Processing this data efficiently is typically an ongoing endeavor, and how it is designed almost always affects the end-user experience of a product. Two popular modes of processing da... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/asynchronous-vs-batch-processing-in-distributed-systems/</link>
                <guid isPermaLink="false">66d0335915ea3036a9539915</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ distributed systems ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anant Chowdhary ]]>
                </dc:creator>
                <pubDate>Wed, 20 Mar 2024 15:13:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/pexels-sydney-troxell-223521-718759.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Distributed Systems often process and store huge amounts of data. Processing this data efficiently is typically an ongoing endeavor, and how it is designed almost always affects the end-user experience of a product.</p>
<p>Two popular modes of processing data are Batch Processing and Asynchronous Processing. We'll learn more about both in this article, along with when to use each approach. </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-batch-processing-of-data">Batch Processing of Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-batch-processing">What is Batch Processing</a>?</p>
</li>
<li><a class="post-section-overview" href="#when-do-we-use-batch-procesing">When Do We Use Batch Processing</a>?</li>
<li><a class="post-section-overview" href="#heading-real-world-example-of-batch-processing-of-data">Real World Example of Batch Processing of Data</a></li>
<li><p><a class="post-section-overview" href="#heading-what-does-batch-processing-look-like-in-code">What Does Batch Processing Look Like in Code</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-asynchronous-processing-of-data">Asynchronous Processing of Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-asynchronous-processing">What is Asynchronous Processing</a>?</p>
</li>
<li><a class="post-section-overview" href="#when-do-we-use-asynchronous-procesing">When Do We Use Asynchronous Processing</a></li>
<li><a class="post-section-overview" href="#heading-real-world-example-of-asynchronous-processing-of-data">Real World Example of Asynchronous Processing of Data</a></li>
<li><p><a class="post-section-overview" href="#heading-what-does-async-processing-look-like-in-code">What Does Async Processing Look Like in Code</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ol>
<h2 id="heading-batch-processing-of-data">Batch Processing of Data</h2>
<h3 id="heading-what-is-batch-processing">What is Batch Processing?</h3>
<p>Batch Processing, as you may have guessed, waits for a certain amount of data to be accumulated, and then processes this <em>batch</em> of data in one go. In other words, this means that in most scenarios we would wait for some number of events to complete and then process the data.</p>
<p>This is different from asynchronous processing of data, where we process an event and its associated data as soon as it occurs. More on that soon.</p>
<p>Now that you know a bit more about batch processing, it'll be useful to see a couple of real world examples. </p>
<h3 id="heading-when-do-we-use-batch-processing">When Do We Use Batch Processing?</h3>
<p>Batch processing is used in lots of scenarios, such as: </p>
<ol>
<li>Large volume of data: When we have a very large amount of data, it is often more resource-efficient to let the data collect over a period of time and then process it.</li>
<li>Data that isn't time sensitive: Since batch processing waits for data to collect, it is generally not suitable for processing data that's very time sensitive. On the other hand, it is possible to process batches of data within short intervals of time.</li>
<li>Scheduled Processing of data: In lots of instances, we need a large amount of data to be processed at regular intervals. Automated system backup and updates, for example, are generally scheduled for particular intervals. Batch processing can be very useful in such scenarios.</li>
</ol>
<h3 id="heading-real-world-example-of-batch-processing-of-data">Real World Example of Batch Processing of Data</h3>
<p>A popular real world use case for batch processing is credit card transactions. </p>
<p>Many financial institutions choose to settle credit card transactions in batches instead of settling them in real time. Since the settlement of transactions is generally not very time sensitive, this gives systems the time to run various other analyses / jobs on the transactions such as fraud detection, currency conversions etc. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/BatchProcessing.drawio-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Credit Card Transactions and Batch Processing</em></p>
<p>The diagram above shows a very high level example of a lifecycle of a credit card transaction. The steps are as follows: </p>
<ol>
<li>The credit card transaction takes place at the Point of Sale (POS).</li>
<li>A gateway forwards the request to a serverless component that writes the transaction to a <em>staging</em> database where the transaction is stored temporarily.</li>
<li>At the end of the business day, the transactions in the staging database are reconciled and go through fraud detection. This is the component where batch processing takes place (note that we waited for some data to collect, and processed a large amount of data). </li>
</ol>
<h3 id="heading-what-does-batch-processing-look-like-in-code">What Does Batch Processing Look Like in Code?</h3>
<p>We saw an example of a distributed system in the above example. How would batch processing look like in code? </p>
<p>Below you'll see some code that lets you process a batch of SQS messages:</p>
<pre><code class="lang-python3">import boto3 

def process_batch_messages(sqs, queue_url):
    partial_response = sqs.receive_message(
        QueueUrl=queue_url
        MaxNumberOfMessages=10 # This sets the maximum batch size to 10
        WaitTimeSeconds=10 # We wait for a maximum of 10 seconds
    )
    if 'Messages' in partial_response:
        messages = partial_response['Messages']
        for each message in messages:
            # do something with each message

            # remove the message from the queue after processing
            sqs.delete_message(QueueUrl=queue_url, ReceiptHandle=message['ReceiptHandle'])


if __name__ == '__main__':
    # Initialize sqs client
        sqs = boto3.client(
        'sqs',
        aws_access_key_id='Your access key id',
        aws_secret_access_key='your secret access key,
        region_name='Your AWS region'
    )
    your_queue_url = 'your-queue-url'
    process_batch_messages(sqs, your_queue_url)
</code></pre>
<p>The above code waits for the earlier of two events: either 10 seconds having passed, or a batch size of 10 being reached within the queue. </p>
<h2 id="heading-asynchronous-processing-of-data">Asynchronous Processing of Data</h2>
<h3 id="heading-what-is-asynchronous-processing">What is Asynchronous Processing?</h3>
<p>The word asynchronous is generally defined as "events that are not coordinated in time". As the definition suggests, asynchronous processing of data does <em>not</em> rely on coordination of data events, and these events are processed as and when they occur. </p>
<p>This means that as soon as an event occurs, the event is processed and the data corresponding to the event may be stored in a sub system, passed on to another component in the system, or may simply lead to another event being fired off. </p>
<h3 id="heading-when-do-we-use-asynchronous-processing">When Do We Use Asynchronous Processing?</h3>
<p>You'll use asynchronous processing of data (sometimes also referred to as async) in various scenarios. </p>
<ol>
<li>Microservices: Microservices often involve a request that needs an immediate response. Since this processing is done "per event", this would require async processing of data, so in most cases results are returned to clients within a very short period of time (low latency).</li>
<li>User Interfaces: Often, components in user facing UI components need to use async processing of data. For instance, multiple data fetches can be performed in the background using async calls when a user is using an application. This ensures that the application works smoothly and responsively without having the need for the UI components to "freeze".</li>
<li>Systems that require real time responses: Many interactive systems require real time processing of data. In the past few years, video calls and meetings have become increasingly popular. Since systems like these require immediate requests and responses (and in some cases streams of data being processed), async processing of data is used here. </li>
</ol>
<h3 id="heading-real-world-example-of-asynchronous-processing-of-data">Real World Example of Asynchronous Processing of Data</h3>
<p>Chat apps are a great example of asynchronous processing of data. Here, if a user 1 types a message and sends it to user 2, the message must be written to the required databases / systems, delivered to user 2, and possibly read by user 2 without any delay. </p>
<p>Since this is <em>real time</em> processing of the event that occurred here (the event being that a message was sent), this is an example of asynchronous processing of data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/AsyncProcessing.drawio-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Exchange of messages in a chat app</em></p>
<p>In the above diagram we see that User 1 sends a message through their phone. The message gets routed to a message server which ultimately creates an entry in a messages database (Messages DB). </p>
<p>Now that MessagesDB has an entry, an event is fired off that is consumed by the Notification Pusher. This then communicates with User 2's notification queue to put a notification related to the message in their notification queue. </p>
<p>Whenever User 2's device comes online or has access to the internet, they receive a message notification.</p>
<p>Note that we did not wait for any data to collect, nor did we process this data after any specific time delay. We processed the event as soon as it happened. So this is an example of asynchronous processing of data. </p>
<h3 id="heading-what-does-async-processing-look-like-in-code">What Does Async Processing Look Like in Code?</h3>
<p>Can we modify the code that we saw in the section for batch processing to work for async processing? Remember that we said "<em>this code waits for the earlier of two events: 10 seconds having passed, or a batch size of 10 being reached within the queue</em>". </p>
<p>If we change the batch size to 1, we would effectively process a message as soon as it is received.</p>
<pre><code><span class="hljs-keyword">import</span> boto3 

def process_async_messages(sqs, queue_url, batch_size):
    partial_response = sqs.receive_message(
        QueueUrl=queue_url
        MaxNumberOfMessages=batch_size # This sets the maximum batch size
        WaitTimeSeconds=<span class="hljs-number">10</span> # We wait <span class="hljs-keyword">for</span> a maximum <span class="hljs-keyword">of</span> <span class="hljs-number">10</span> seconds
    )
    <span class="hljs-keyword">if</span> <span class="hljs-string">'Messages'</span> <span class="hljs-keyword">in</span> partial_response:
        messages = partial_response[<span class="hljs-string">'Messages'</span>]
        <span class="hljs-keyword">for</span> each message <span class="hljs-keyword">in</span> messages:
            # <span class="hljs-keyword">do</span> something <span class="hljs-keyword">with</span> each message

            # remove the message <span class="hljs-keyword">from</span> the queue after processing
            sqs.delete_message(QueueUrl=queue_url, ReceiptHandle=message[<span class="hljs-string">'ReceiptHandle'</span>])


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    # Initialize sqs client
        sqs = boto3.client(
        <span class="hljs-string">'sqs'</span>,
        aws_access_key_id=<span class="hljs-string">'Your access key id'</span>,
        aws_secret_access_key=<span class="hljs-string">'your secret access key,
        region_name='</span>Your AWS region<span class="hljs-string">'
    )
    your_queue_url = '</span>your-queue-url<span class="hljs-string">'
    process_batch_messages(sqs, your_queue_url, 1)</span>
</code></pre><p>Note that in the above code we modified the <code>process_batch_messages</code> to accept a <code>batch_size</code> parameter and renamed the method to <code>process_async_messages</code>. This method processes a message as soon as the queue receives a method (assuming the queue has received a message within the wait time of 10 seconds) </p>
<h2 id="heading-summary">Summary</h2>
<p>Let's summarize batch and asynchronous data processing. </p>
<p>Batch Processing is a paradigm where you wait for an amount of data to collect or some time to pass before the data is processed. </p>
<p>Batch processing is often used in scenarios where you have large volumes of data, data that isn't time sensitive, and data that can be processed on a set schedule. The example we discussed above was that of a credit card transaction.</p>
<p>Asynchronous processing of data, on the other hand, is used to process data related to events as soon as they occur. </p>
<p>This approach is often used when dealing with data processed in microservices, user interfaces, and in general with systems needing real time request-response processing. We looked at an example of a chat app in the above discussion and learnt how asynchronous processing of data is applicable to the scenario. </p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
