<?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[ scalability - 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[ scalability - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 18 May 2026 22:34:54 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/scalability/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Django REST APIs for Performance: Profiling, Caching, and Scaling. ]]>
                </title>
                <description>
                    <![CDATA[ Performance problems in APIs rarely start as performance problems. They usually start as small design decisions that worked perfectly when the application had ten users, ten records, or a single developer testing locally. Over time, as traffic increa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-django-rest-apis-for-performance/</link>
                <guid isPermaLink="false">6994b1d13e0696149c7c229c</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ django rest framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ caching ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mari ]]>
                </dc:creator>
                <pubDate>Tue, 17 Feb 2026 18:22:09 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1771352481135/11be538b-aaf5-4c1e-8ee2-99deea5f180e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Performance problems in APIs rarely start as performance problems. They usually start as small design decisions that worked perfectly when the application had ten users, ten records, or a single developer testing locally. Over time, as traffic increases and data grows, those same decisions begin to slow everything down.</p>
<p>In this article, we’ll walk step by step through how performance issues arise in Django REST APIs, how to see them clearly using profiling tools, and how to fix them using query optimization, caching, pagination, and basic scaling strategies.</p>
<p>This article will be most useful for developers who already understand Django, the Django REST Framework, and REST concepts, but are new to performance optimization.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-django-rest-apis-become-slow">Why Django REST APIs Become Slow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-profiling-finding-the-real-bottlenecks">Profiling: Finding the Real Bottlenecks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-logging-sql-queries">Logging SQL Queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary-and-next-steps">Summary and Next Steps</a></p>
</li>
</ul>
<h2 id="heading-why-django-rest-apis-become-slow">Why Django REST APIs Become Slow</h2>
<p>Before optimizing anything, it’s important to understand why APIs become slow in the first place.</p>
<p>Most performance issues in Django REST APIs come from three main sources:</p>
<ol>
<li><p>Too many database queries</p>
</li>
<li><p>Doing expensive work repeatedly</p>
</li>
<li><p>Returning more data than necessary</p>
</li>
</ol>
<p>Django is fast by default, but it does exactly what you ask it to do. If your API endpoint triggers 300 database queries, Django will happily run all 300.</p>
<p>Now let’s look at some common causes of performance issues in Django REST APIs.</p>
<h3 id="heading-1-n1-query-problems-in-serializers">1. N+1 Query Problems in Serializers</h3>
<p>This happens when you loop over objects and access related fields, causing a separate query for each object.</p>
<pre><code class="lang-python"><span class="hljs-comment"># models.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Author</span>(<span class="hljs-params">models.Model</span>):</span>
    name = models.CharField(max_length=<span class="hljs-number">100</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">200</span>)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

<span class="hljs-comment"># views.py (naive approach)</span>
posts = Post.objects.all()
<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-comment"># This triggers a query per post to fetch the author</span>
    print(post.author.name)
</code></pre>
<p>If you have 100 posts, this runs 101 queries: 1 for posts and 100 for authors. Django lazily loads related objects by default, so without intervention, your API performs repetitive database work that slows response times.</p>
<h3 id="heading-2-fetching-related-objects-inefficiently">2. Fetching Related Objects Inefficiently</h3>
<pre><code class="lang-python"><span class="hljs-comment"># Naive queryset fetching all related objects separately</span>
posts = Post.objects.all()
authors = [post.author <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts]  <span class="hljs-comment"># triggers extra queries per post</span>
</code></pre>
<p>Each access to <code>post.author</code> triggers a new query. Even though you already fetched all posts, Django lazily loads related objects by default. This creates many extra queries, slowing down your API.</p>
<h3 id="heading-3-serializing-large-datasets-without-pagination">3. Serializing Large Datasets Without Pagination</h3>
<p>Returning large query sets all at once can slow down your API and increase memory usage.</p>
<pre><code class="lang-python"><span class="hljs-comment"># views.py</span>
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">from</span> rest_framework.decorators <span class="hljs-keyword">import</span> api_view
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> PostSerializer

<span class="hljs-meta">@api_view(['GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">all_posts</span>(<span class="hljs-params">request</span>):</span>
    posts = Post.objects.all()  <span class="hljs-comment"># retrieves all posts at once</span>
    serializer = PostSerializer(posts, many=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> Response(serializer.data)
</code></pre>
<p>If your database has thousands of posts, this endpoint fetches everything in memory, serializes it, and sends it over the network. It’s slow and can crash under load. Later, we’ll learn to paginate results efficiently.</p>
<h3 id="heading-4-recomputing-expensive-work-repeatedly">4. Recomputing Expensive Work Repeatedly</h3>
<p>Some endpoints calculate the same values on every request instead of caching or precomputing.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">expensive_view</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-comment"># Simulate expensive computation</span>
    result = sum([i**<span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1000000</span>)])
    <span class="hljs-keyword">return</span> JsonResponse({<span class="hljs-string">"result"</span>: result})
</code></pre>
<p>Even if the data doesn’t change often, this computation happens on every request, consuming CPU time unnecessarily.  </p>
<p>Performance optimization is about reducing unnecessary work.  </p>
<p>At this point, it might be tempting to jump straight into fixes like caching responses or optimizing database queries. But doing that without evidence often leads to wasted effort or even new problems.</p>
<p>Before changing anything, you need to understand where your API is actually spending time. Is it the database? Is it serialization? Is it Python code running repeatedly on every request? This is where profiling becomes essential.</p>
<h2 id="heading-profiling-finding-the-real-bottlenecks">Profiling: Finding the Real Bottlenecks</h2>
<p>Optimizing without profiling is guessing. Profiling helps you answer one question:</p>
<blockquote>
<p>Where is my API actually spending time?</p>
</blockquote>
<p>In practice, profiling means observing an API while it runs and collecting data about what it’s doing. This includes how many database queries are executed, how long those queries take, and how much time is spent in Python code, such as serializers or business logic.</p>
<p>By profiling first, you avoid making assumptions and can focus on fixing the parts of your API that are truly slowing things down.</p>
<h3 id="heading-measuring-query-count-in-a-view">Measuring Query Count in a View</h3>
<p>During development, Django keeps track of all executed queries. You can inspect them directly:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> connection
<span class="hljs-keyword">from</span> rest_framework.decorators <span class="hljs-keyword">import</span> api_view
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> PostSerializer

<span class="hljs-meta">@api_view(["GET"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post_list</span>(<span class="hljs-params">request</span>):</span>
    posts = Post.objects.all()
    serializer = PostSerializer(posts, many=<span class="hljs-literal">True</span>)

    response = Response(serializer.data)

    print(<span class="hljs-string">f"Total queries executed: <span class="hljs-subst">{len(connection.queries)}</span>"</span>)

    <span class="hljs-keyword">return</span> response
</code></pre>
<p>If this prints 101 queries for 100 posts, you likely have an N+1 problem. This simple check confirms whether the database layer is the bottleneck.</p>
<p>One of the easiest ways to profile Django applications during development is by using tools that expose this information directly while requests are being processed.</p>
<h3 id="heading-using-the-django-debug-toolbar">Using the Django Debug Toolbar</h3>
<p>The Django Debug Toolbar is one of the simplest ways to understand performance during development. It acts as a lightweight profiling tool that shows what happens behind the scenes when a request is handled.</p>
<p>It shows you:</p>
<ul>
<li><p>How many SQL queries were executed</p>
</li>
<li><p>How long each query took</p>
</li>
<li><p>whether queries are duplicated</p>
</li>
<li><p>Which parts of the request lifecycle are slow</p>
</li>
</ul>
<h4 id="heading-how-to-install-and-enable-the-django-debug-toolbar">How to Install and Enable the Django Debug Toolbar</h4>
<p>First, install it:</p>
<pre><code class="lang-bash">pip install django-debug-toolbar
</code></pre>
<p>In settings.py:</p>
<pre><code class="lang-bash">INSTALLED_APPS = [
    ...
    <span class="hljs-string">"debug_toolbar"</span>,
]

MIDDLEWARE = [
    ...
    <span class="hljs-string">"debug_toolbar.middleware.DebugToolbarMiddleware"</span>,
]

INTERNAL_IPS = [
    <span class="hljs-string">"127.0.0.1"</span>,
]
</code></pre>
<p>In urls.py:</p>
<pre><code class="lang-bash">import debug_toolbar
from django.urls import path, include

urlpatterns = [
    ...
    path(<span class="hljs-string">"__debug__/"</span>, include(debug_toolbar.urls)),
]
</code></pre>
<p>When you load an endpoint in the browser during development, the toolbar displays total SQL queries, execution time, and duplicate queries. This makes inefficiencies immediately visible.</p>
<p>When you load an API endpoint and see 150 SQL queries for a single request, that’s a strong signal that something is wrong, often an N+1 query problem or inefficient serializer behavior.</p>
<h3 id="heading-logging-sql-queries">Logging SQL Queries</h3>
<p>Django allows you to log all executed SQL queries. This is especially useful when debugging API views.</p>
<p>Seeing the raw SQL makes inefficiencies obvious, such as repeated <code>SELECT</code> statements for the same table.</p>
<h4 id="heading-how-to-enable-sql-query-logging">How to Enable SQL Query Logging</h4>
<p>You can configure Django to log all SQL queries in settings.py:</p>
<pre><code class="lang-bash">LOGGING = {
    <span class="hljs-string">"version"</span>: 1,
    <span class="hljs-string">"handlers"</span>: {
        <span class="hljs-string">"console"</span>: {
            <span class="hljs-string">"class"</span>: <span class="hljs-string">"logging.StreamHandler"</span>,
        },
    },
    <span class="hljs-string">"loggers"</span>: {
        <span class="hljs-string">"django.db.backends"</span>: {
            <span class="hljs-string">"handlers"</span>: [<span class="hljs-string">"console"</span>],
            <span class="hljs-string">"level"</span>: <span class="hljs-string">"DEBUG"</span>,
        },
    },
}
</code></pre>
<p>With this configuration, every SQL query will be printed to the console when your API runs. Repeated SELECT statements or unexpected queries become obvious.</p>
<h3 id="heading-profiling-api-response-time">Profiling API Response Time</h3>
<p>Database queries are only one part of API performance. Beyond queries, it’s also important to measure the total response time of an endpoint.</p>
<p>Profiling response time helps you understand whether delays are caused by database access or by other parts of the request lifecycle. For example, if an endpoint takes 1.2 seconds to respond but only 50 milliseconds are spent on database queries, the bottleneck is likely in serialization, business logic, or repeated computations in Python.</p>
<p>By comparing query time and total response time, profiling helps you identify what to fix first instead of optimizing the wrong layer of the system.</p>
<h4 id="heading-how-to-measure-total-response-time">How to Measure Total Response Time</h4>
<pre><code class="lang-bash">import time
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view([<span class="hljs-string">"GET"</span>])
def example_view(request):
    start_time = time.time()

    <span class="hljs-comment"># Simulate work</span>
    data = {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello world"</span>}

    response = Response(data)

    end_time = time.time()
    <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Response time: {end_time - start_time:.4f} seconds"</span>)

    <span class="hljs-built_in">return</span> response
</code></pre>
<p>If database queries are fast but the total response time is high, the bottleneck may be serialization or expensive Python logic.  </p>
<p>Once you’ve identified that database access is a significant contributor to slow response times, the next step is to look more closely at how Django retrieves related data.</p>
<h3 id="heading-sql-query-optimization-in-django-rest-apis">SQL Query Optimization in Django REST APIs</h3>
<p>One of the most common reasons Django REST APIs become slow is inefficient access to related objects. This often manifests as the N+1 query problem, where fetching related objects triggers a separate database query for each item. Identifying and fixing this problem can significantly reduce the number of queries and improve API performance.</p>
<h4 id="heading-understanding-the-n1-query-problem">Understanding the N+1 Query Problem</h4>
<p>Consider a simple example:</p>
<ul>
<li><p>You fetch a list of posts</p>
</li>
<li><p>Each post has an author</p>
</li>
<li><p>For every post, Django fetches the author separately</p>
</li>
</ul>
<p>If you have 100 posts, this results in 101 queries: 1 for the posts and 100 for the authors. This happens because Django lazily loads related objects by default. Without intervention, your API performs repetitive database work that slows down response times.</p>
<h4 id="heading-solving-the-problem-with-selectrelated-and-prefetchrelated">Solving the Problem with <code>select_related</code> and <code>prefetch_related</code></h4>
<p>Django provides built-in tools to control how related objects are loaded efficiently: <code>select_related</code> and <code>prefetch_related</code>.</p>
<p><strong>1. Using</strong> <code>select_related</code></p>
<p><code>select_related</code> is designed for foreign key and one-to-one relationships. It performs an SQL join and retrieves related objects in a single query.</p>
<p>Use it when:</p>
<ul>
<li><p>You know you will access related objects</p>
</li>
<li><p>The relationship is one-to-one or many-to-one</p>
</li>
</ul>
<pre><code class="lang-bash">posts = Post.objects.select_related(<span class="hljs-string">"author"</span>)

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.author.name)  <span class="hljs-comment"># No additional queries</span>
</code></pre>
<p>This performs a SQL JOIN and retrieves posts and authors in a single query, eliminating the N+1 problem.</p>
<p>It reduces multiple queries into just one, avoiding repeated database hits.</p>
<p><strong>2. Using</strong> <code>prefetch_related</code></p>
<p><code>prefetch_related</code> is used for many-to-many and reverse foreign key relationships. It performs separate queries for each related table but combines the results in Python.</p>
<p>Use it when:</p>
<ul>
<li><p>A SQL join would produce too much duplicated data</p>
</li>
<li><p>You are dealing with collections of related objects</p>
</li>
</ul>
<h4 id="heading-example-how-to-optimize-a-many-to-many-relationship">Example: How to Optimize a Many-to-Many Relationship</h4>
<p>Consider a blog application where posts can have multiple tags:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># models.py</span>
class Tag(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=200)
    tags = models.ManyToManyField(Tag)
</code></pre>
<p>Now imagine fetching posts and accessing their tags:</p>
<pre><code class="lang-bash">posts = Post.objects.all()

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.tags.all())  <span class="hljs-comment"># Triggers additional queries</span>
</code></pre>
<p>If you have 100 posts, Django may execute:</p>
<ul>
<li><p>1 query to fetch posts</p>
</li>
<li><p>1 query per post to fetch related tags</p>
</li>
</ul>
<p>This results in many unnecessary database hits.</p>
<p>You can optimize this using <code>prefetch_related</code>:</p>
<pre><code class="lang-bash">posts = Post.objects.prefetch_related(<span class="hljs-string">"tags"</span>)

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.tags.all())  <span class="hljs-comment"># Uses prefetched data</span>
</code></pre>
<p>With this approach, Django performs one query for posts and one query for all related tags. It then matches them in Python, eliminating repeated database queries.</p>
<p>Together, these tools allow you to optimize your queries and eliminate the N+1 problem efficiently.</p>
<h4 id="heading-common-beginner-mistakes">Common Beginner Mistakes</h4>
<p>Even after applying these optimizations, it’s easy to make mistakes. Watch out for:</p>
<ul>
<li><p>Forgetting that serializers can trigger additional queries</p>
</li>
<li><p>Using <code>select_related</code> on many-to-many relationships</p>
</li>
<li><p>Assuming Django automatically optimizes queries</p>
</li>
<li><p>Not checking the query count after adding serializers</p>
</li>
</ul>
<p>Paying attention to these pitfalls ensures your API remains fast and scalable.</p>
<h3 id="heading-caching-in-django-rest-apis">Caching in Django REST APIs</h3>
<p>Even after optimizing database queries, API performance can still suffer if the same computations or database lookups are performed repeatedly. This is where caching comes in. Caching is a technique for storing the results of expensive operations so they can be retrieved more quickly the next time they are needed.</p>
<p>At its core, caching exists because computers have multiple layers of memory with different speeds:</p>
<ul>
<li><p>CPU registers (fastest)</p>
</li>
<li><p>L1, L2, L3 caches</p>
</li>
<li><p>Main memory (RAM)</p>
</li>
<li><p>SSD storage</p>
</li>
<li><p>HDD storage (slowest)</p>
</li>
</ul>
<p>Each layer trades speed for size: the closer the data is to the CPU, the faster it can be accessed. Software systems use the same principle; by storing frequently accessed data in a “closer” or faster location, applications can respond more quickly.</p>
<h4 id="heading-cache-eviction">Cache Eviction</h4>
<p>Caches are limited in size, so when a cache is full, some data must be removed to make room for new data. This process is called cache eviction.</p>
<p>Common eviction strategies include:</p>
<ul>
<li><p><strong>Least Recently Used (LRU):</strong> removes the data that hasn’t been accessed for the longest time</p>
</li>
<li><p><strong>Random Replacement:</strong> removes a random item from the cache</p>
</li>
</ul>
<p>The goal is to keep the data that is most likely to be requested again while freeing space for new data. Understanding this helps developers use caching effectively.</p>
<h4 id="heading-caching-in-application-architectures">Caching in Application Architectures</h4>
<p>Caching exists at several levels in modern software systems:</p>
<ul>
<li><p><strong>Client-side caching:</strong> Web browsers cache HTTP responses to reduce the need for repeated network requests. This is controlled with HTTP headers like <code>Cache-Control</code>.</p>
</li>
<li><p><strong>CDN caching:</strong> Content Delivery Networks store static assets closer to users, reducing latency and server load.</p>
</li>
<li><p><strong>Backend caching:</strong> Backend services cache results from database queries, computed values, or API responses. This is where Django caching is most commonly applied.</p>
</li>
</ul>
<p>By applying caching strategically at the backend, APIs can serve data faster while reducing computation and database load.</p>
<h4 id="heading-caching-in-django">Caching in Django</h4>
<p>Django provides a flexible caching framework that supports multiple backends, including in-memory, file-based, database-backed, and third-party stores like Redis. The main types of caching in Django are:</p>
<ol>
<li><p><strong>Per-view caching:</strong> caches the entire output of a view. Ideal for endpoints where responses rarely change.</p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> django.views.decorators.cache <span class="hljs-keyword">import</span> cache_page

<span class="hljs-meta"> @cache_page(60 * 15)  # cache for 15 minutes</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_view</span>(<span class="hljs-params">request</span>):</span>
</code></pre>
<ol start="2">
<li><p>Template fragment caching: caches specific parts of a template to avoid repeated rendering.</p>
</li>
<li><p>Low-level caching: gives full control over what is cached and for how long, making it ideal for API responses.</p>
</li>
</ol>
</li>
</ol>
<p>    By combining these approaches, you can reduce repeated work in your API, lower database load, and speed up response times.</p>
<h3 id="heading-when-to-use-redis">When to Use Redis</h3>
<p>While Django’s built-in caching backends are sufficient for many projects, high-traffic APIs often require a shared, in-memory cache. This is where Redis excels. Redis is designed for fast access, low latency, and can handle frequent reads across multiple servers.</p>
<p>You should consider using Redis when:</p>
<ul>
<li><p>Data is read frequently but changes infrequently</p>
</li>
<li><p>Low latency is important for API responses</p>
</li>
<li><p>You need cache expiration and eviction policies</p>
</li>
<li><p>You want a shared cache across multiple servers or services</p>
</li>
</ul>
<p>Redis is particularly effective for API endpoints that serve the same data to many users, such as frequently accessed lists or computed results.</p>
<h3 id="heading-common-beginner-mistakes-1">Common Beginner Mistakes</h3>
<p>Caching is powerful, but it’s easy to misuse. Some common pitfalls include:</p>
<ul>
<li><p><strong>Caching everything blindly:</strong> not all data benefits from caching</p>
</li>
<li><p><strong>Forgetting cache invalidation:</strong> stale data can lead to incorrect responses</p>
</li>
<li><p><strong>Using cache where query optimization would suffice:</strong> sometimes optimizing database queries is a better solution than caching.</p>
</li>
</ul>
<p>Remember: caching should complement good database design, not replace it.</p>
<h3 id="heading-pagination-and-limiting-expensive-datasets">Pagination and Limiting Expensive Datasets</h3>
<p>Even with caching, returning large datasets in a single request can slow down your API and increase memory usage. Pagination is a simple and effective way to limit the amount of data returned at once.</p>
<p>Pagination helps by reducing:</p>
<ul>
<li><p>Database load</p>
</li>
<li><p>Memory usage</p>
</li>
<li><p>Serialization time</p>
</li>
<li><p>Network transfer size</p>
</li>
</ul>
<p>Django REST Framework provides built-in pagination classes that make it easy to paginate endpoints. As a rule of thumb, always paginate list endpoints unless there is a strong reason not to.</p>
<h3 id="heading-load-testing-and-measuring-improvement">Load Testing and Measuring Improvement</h3>
<p>Optimizations are only meaningful if you can measure their impact. Load testing simulates multiple users accessing your API simultaneously, helping you answer key questions:</p>
<ul>
<li><p>How many requests per second can my API handle?</p>
</li>
<li><p>Where does the API start to break under load?</p>
</li>
<li><p>Did caching, query optimization, and pagination actually improve performance?</p>
</li>
</ul>
<p>By running load tests before and after optimization, you can validate that your changes have the desired effect and avoid optimizing the wrong parts of your system.</p>
<h2 id="heading-summary-and-next-steps">Summary and Next Steps</h2>
<p>Optimizing Django REST APIs isn’t about chasing every tiny micro-optimization. It’s about reducing unnecessary work and focusing on the parts of your API that actually slow down performance.</p>
<h4 id="heading-key-takeaways">Key Takeaways</h4>
<ul>
<li><p><strong>Profile before optimizing:</strong> Identify the real bottlenecks before making changes.</p>
</li>
<li><p><strong>Reduce database queries:</strong> Use techniques like <code>select_related</code>, <code>prefetch_related</code>, and avoid N+1 queries.</p>
</li>
<li><p><strong>Cache frequently accessed data:</strong> Use Django caching and Redis to reduce repeated computations.</p>
</li>
<li><p><strong>Paginate large datasets:</strong> Limit memory usage and network load by returning data in chunks.</p>
</li>
<li><p><strong>Measure performance changes:</strong> Always verify that your optimizations have a real impact.</p>
</li>
</ul>
<h4 id="heading-next-steps-for-your-apis">Next Steps for Your APIs</h4>
<ol>
<li><p><strong>Add profiling to your existing APIs</strong> to understand where time is spent.</p>
</li>
<li><p><strong>Identify one slow endpoint</strong> and focus on optimizing it first.</p>
</li>
<li><p><strong>Optimize database queries</strong> using Django ORM best practices.</p>
</li>
<li><p><strong>Introduce caching carefully</strong>; avoid caching everything blindly.</p>
</li>
<li><p><strong>Measure the results</strong> with load testing and performance metrics.</p>
</li>
</ol>
<p>Remember: Performance optimization is not a one-time task. It’s a habit built by continuously observing how your system works, testing improvements, and applying changes where they make the most impact.</p>
<h2 id="heading-read-more">Read More</h2>
<ol>
<li><p><a target="_blank" href="https://www.django-rest-framework.org/topics/performance/">DRF Performance</a></p>
</li>
<li><p><a target="_blank" href="https://docs.djangoproject.com/en/stable/topics/db/optimization/">Django ORM Optimization</a></p>
</li>
<li><p><a target="_blank" href="https://docs.djangoproject.com/en/stable/topics/db/optimization/#select-related">Understanding N+1 queries</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Dynamic Performance Test in Apache JMeter ]]>
                </title>
                <description>
                    <![CDATA[ As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-your-first-dynamic-performance-test-in-apache-jmeter/</link>
                <guid isPermaLink="false">6900f3ca65a053299e38eab3</guid>
                
                    <category>
                        <![CDATA[ Scale Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jmeter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mah Noor ]]>
                </dc:creator>
                <pubDate>Tue, 28 Oct 2025 16:48:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761335397152/cb105a44-4c18-4998-9ffb-d520df0e6510.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.</p>
<p>For me personally, there is a deep satisfaction that comes with seeing your product come alive under load to find out how it’ll actually work in production when thousands of users will be using it.</p>
<p>Performance testing is about discovering how your system performs under real-world pressure in terms of load, concurrency, and throughput. One of the key aspects of performance testing is ensuring that the APIs can endure the expected load. You can do this using tools like Apache JMeter and K6.</p>
<p>In this tutorial, we’ll explore how you can build your first end-to-end performance test in Apache JMeter. You will be learning to create a test suite that is dynamic (the test can be run with any test data) and that’s one-click executable (the test execution can be done through the GUI as well as the CLI).</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-add-an-assertion">Step 7: Add an Assertion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-8-add-listeners">Step 8: Add Listeners</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-9-run-your-test">Step 9: Run Your Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-11-analyze-the-results">Step 11: Analyze the Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pro-tips">Pro Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-folder-structure">Example Folder Structure:</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, make sure you have:</p>
<ul>
<li><p><a target="_blank" href="https://jmeter.apache.org/download_jmeter.cgi"><strong>Apache JMeter (5.5 or above)</strong></a> installed.</p>
</li>
<li><p><a target="_blank" href="https://www.java.com/en/download/manual.jsp"><strong>Java 8 or later</strong></a> configured on your system.</p>
</li>
</ul>
<p>You can check if JMeter is installed by running the command below:</p>
<pre><code class="lang-plaintext">jmeter -v
</code></pre>
<p><strong>Note:</strong> This tutorial will use the <a target="_blank" href="https://jsonplaceholder.typicode.com/">JSONPlaceholder</a> public API. You’ll learn how you can get a post_id and use it in a chain request to get user details.</p>
<p>Let’s get started.</p>
<h2 id="heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</h2>
<p>Apache JMeter is an open-source API load and stress testing tool. It’s a powerful testing tool that supports a wide range of protocols, including HTTP, HTTPS, FTP, JDBC, SOAP, and REST.</p>
<p>JMeter helps you answer critical questions about your APIs, like:</p>
<ul>
<li><p>How does my API perform under heavy load?</p>
</li>
<li><p>What’s the maximum number of users it can handle before it starts failing?</p>
</li>
<li><p>Which requests or endpoints are slowing things down?</p>
</li>
</ul>
<p>Let’s go through the step-by-step process of building a dynamic load testing suite with JMeter.</p>
<h3 id="heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</h3>
<p>Once JMeter opens, you’ll see an empty Test Plan. Think of this as your main workspace, which holds everything: Test configuration, users, requests, assertions, and results.</p>
<p>Right-click on <strong>Test Plan → Add → Threads (Users) → Thread Group</strong> to add a thread group. A thread group is essentially a test suite containing our test cases.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761045558747/ad3a2fe3-de59-420f-ba9d-1a36323e1d9e.png" alt="Add Thread Group" width="1920" height="1009" loading="lazy"></p>
<h3 id="heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</h3>
<p>To configure the thread group, fill out the following input fields:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Setting</td><td>Value</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>Number of Threads (Users)</td><td>5</td><td>This represents the number of concurrent users. In this case, it will be ‘5’</td></tr>
<tr>
<td>Ramp-up Period (seconds)</td><td>10</td><td>This means the time it takes the threads to reach the maximum value.</td></tr>
<tr>
<td>Loop Count</td><td>2</td><td>This specifies the number of times you want your thread group executed.</td></tr>
</tbody>
</table>
</div><p>You’ve now created a small, controlled load test of 10 total requests (5 users × 2 loops).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049951497/8221336c-5f10-4161-81fa-d0ad27c7164f.png" alt="Thread Group" class="image--center mx-auto" width="1920" height="982" loading="lazy"></p>
<h3 id="heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</h3>
<p>When you’re creating a suite of 100s of APIs, you don’t need to add your request details to all the API samplers in JMeter. JMeter lets you set it once globally by using a config element called HTTP Request Defaults. To add this element, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Config Element → HTTP Request Defaults.</strong></p>
</li>
<li><p>Enter the following:</p>
<ul>
<li><p><strong>Protocol:</strong> <code>https</code></p>
</li>
<li><p><strong>Server Name or IP:</strong> <a target="_blank" href="http://jsonplaceholder.typicode.com"><code>jsonplaceholder.typicode.com</code></a></p>
</li>
</ul>
</li>
</ol>
<p>This means all requests in this test will automatically use this base URL.</p>
<h3 id="heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</h3>
<p>In real projects, APIs rarely use static inputs. Take as an example a login API that you want to run for 100 concurrent users. In a real-world scenario, every login request will have a different username and password.</p>
<p>To replicate this on JMeter, you need to run your test for 100 different login credentials. This means that your test should be <strong>test data-driven</strong>. We can build a data-driven test in JMeter using a <strong>CSV file</strong>:</p>
<ol>
<li><p>Create a file named <code>data.csv</code> with the following content:</p>
<pre><code class="lang-plaintext"> post_id
 1
 2
 3
 4
 5
</code></pre>
</li>
<li><p>Save it in your JMeter project folder.</p>
</li>
<li><p>In JMeter, right-click on <strong>Thread Group → Add → Config Element → CSV Data Set Config.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048312824/4558aae4-23c8-446d-89d0-237aca29619d.png" alt="Add CSV Data Set Config" class="image--center mx-auto" width="1169" height="974" loading="lazy"></p>
</li>
<li><p>Fill in the following fields:</p>
<ul>
<li><p><strong>Filename:</strong> <code>data.csv</code></p>
</li>
<li><p><strong>Variable Names:</strong> <code>post_id</code></p>
</li>
<li><p><strong>Recycle on EOF:</strong> <code>True</code></p>
</li>
<li><p><strong>Stop thread on EOF:</strong> <code>False</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048167041/eae27f5c-6e23-4c7d-8890-b3eb5943bb66.png" alt="CSV Data Set Config" class="image--center mx-auto" width="1437" height="642" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p>Now each user will pick a new <code>post_id</code> for every iteration from the CSV file.</p>
<h3 id="heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</h3>
<p>Now let’s add the actual API call we'll test under load. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051865320/92bf89d0-616c-4d07-9531-3985265e07d7.png" alt="Add an HTTP Request" class="image--center mx-auto" width="1920" height="1017" loading="lazy"></p>
</li>
<li><p>Rename it to <strong>Get Post Data.</strong></p>
</li>
<li><p>Set the following fields:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/posts/${post_id}</code></p>
</li>
</ul>
</li>
</ol>
<p>Here <code>${post_id}</code> dynamically takes its value from your CSV file. The Protocol and Server IP fields will automatically get data from the ‘HTTP Request default’ config element that we added in Step #3.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049282841/a420139c-4622-4d7a-ac7d-4308bb9a1dbc.png" alt="Add a GET Request" class="image--center mx-auto" width="1920" height="904" loading="lazy"></p>
<h3 id="heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</h3>
<p>When the API returns a response, we can extract a value (like <code>userId</code>) from it and use it later. This is used to implement an end-to-end flow where data is gotten (with GET) from an API and sent to the next POST/DELETE API.</p>
<p>For our API, below is the example response:</p>
<pre><code class="lang-plaintext">{
  "userId": 1,
  "id": 3,
  "title": "fugiat veniam minus",
  "body": "This is an example post body"
}
</code></pre>
<p>To extract <code>userId</code>:</p>
<ol>
<li><p>Right-click on <strong>Get Post Data → Add → Post Processors → JSON Extractor.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051791176/b7888a78-efbb-48d3-8aba-fcd21edfd8f2.png" alt="Add JSON Extractor" class="image--center mx-auto" width="1920" height="1018" loading="lazy"></p>
</li>
<li><p>Set the variables below in the JSON Extractor:</p>
<ul>
<li><p><strong>Name:</strong> Extract User ID</p>
</li>
<li><p><strong>Variable Name:</strong> <code>user_id</code></p>
</li>
<li><p><strong>JSON Path Expression:</strong> <code>$.userId</code></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049324410/8a163733-8925-4557-9ace-124b08167f8e.png" alt="JSON Extractor" class="image--center mx-auto" width="1920" height="971" loading="lazy"></p>
<p>Now you can use <code>${user_id}</code> in the next request, making your test fully dynamic.</p>
<h3 id="heading-step-7-add-an-assertion">Step 7: Add an Assertion</h3>
<p>Assertions help you verify that your API responds correctly even under load. You can assert on the API response code, response time, or even the response payload. To add an assertion, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Get Post Data → Add → Assertions → Response Assertion.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049384591/a0293eef-74a0-4d55-b0c4-232d5c5eaa0c.png" alt="Add Response Assertion" class="image--center mx-auto" width="1920" height="1020" loading="lazy"></p>
</li>
<li><p>Configure as:</p>
<ul>
<li><p><strong>Response Field to Test:</strong> <em>Response Code –</em> This will add an assertion for the response code.</p>
</li>
<li><p><strong>Pattern Matching Rules:</strong> <em>Contains</em></p>
</li>
<li><p><strong>Pattern to Test:</strong> 200</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050184412/5a52f600-74f6-48c7-a975-7e39df47afdb.png" alt="Add Response Assertion" class="image--center mx-auto" width="1920" height="1017" loading="lazy"></p>
<p>This ensures JMeter only counts the request as successful if the word <code>fugiat</code> appears in the response.</p>
<h3 id="heading-step-8-add-listeners">Step 8: Add Listeners</h3>
<p>We’ll add listeners to display our test results in different forms, such as visually or in a summary. Let’s add two essential ones:</p>
<ol>
<li><p><strong>View Results Tree</strong>: to view and debug individual requests.</p>
</li>
<li><p><strong>Summary Report</strong>: to view performance metrics like response time, error rate, and throughput.</p>
</li>
</ol>
<p>Add them via <strong>Thread Group → Add → Listener → [Choose Listener]</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049568483/0daa916c-503d-4f91-ad17-1d2bd29a9f72.png" alt="Add Listener in JMeter" class="image--center mx-auto" width="1920" height="1020" loading="lazy"></p>
<h3 id="heading-step-9-run-your-test">Step 9: Run Your Test</h3>
<p>Hit the green <strong>Start</strong> button at the top. JMeter will start sending requests to your API using the dynamic post IDs from your CSV file.</p>
<p>As the test runs:</p>
<ul>
<li><p>Green checkmarks in <strong>View Results Tree</strong> mean successful responses.</p>
</li>
<li><p>Assertion failures will appear in red.</p>
</li>
<li><p><strong>Summary Report</strong> will aggregate key metrics.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050151356/d8c72408-cf91-4c9d-8663-0a65b6943f5b.png" alt="JMeter View Results Tree" class="image--center mx-auto" width="1920" height="1013" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050211424/532dd999-b870-4cf8-ad1e-1a692119b0e0.png" alt="JMeter Summary Report" class="image--center mx-auto" width="1920" height="1024" loading="lazy"></p>
<h3 id="heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</h3>
<p>Let’s take it one step further: we’ll use the extracted <code>user_id</code> from the first response to get user details from the <a target="_blank" href="https://jsonplaceholder.typicode.com/users">GET users call</a>. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
</li>
<li><p>Rename to <strong>Get User Details.</strong></p>
</li>
<li><p>Set:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/users/${user_id}</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050384264/dcc1c333-4e06-4dd9-8dca-9af823fedabd.png" alt="GET Users API" class="image--center mx-auto" width="1920" height="1015" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050365937/736b9954-6d01-45a6-8c16-f6d2ceb60e10.png" alt="Test Execution in JMeter" class="image--center mx-auto" width="1920" height="1021" loading="lazy"></p>
<h3 id="heading-step-11-analyze-the-results">Step 11: Analyze the Results</h3>
<p>Once the test completes, open the <strong>Summary Report</strong>. You’ll see:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Metric</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Sample Count</strong></td><td>Number of total requests sent</td></tr>
<tr>
<td><strong>Average</strong></td><td>Mean response time per request</td></tr>
<tr>
<td><strong>Min/Max</strong></td><td>Fastest and slowest response times</td></tr>
<tr>
<td><strong>Error %</strong></td><td>Percentage of failed requests</td></tr>
<tr>
<td><strong>Throughput</strong></td><td>Requests handled per second</td></tr>
</tbody>
</table>
</div><p>If your error percentage is 0% and throughput is stable, your system handled the load well.</p>
<h3 id="heading-pro-tips">Pro Tips</h3>
<ul>
<li><p><strong>Parameterize everything.</strong> Use multiple CSVs for realistic test flows (users, IDs, tokens).</p>
</li>
<li><p><strong>Add timers</strong> (like <em>Constant Timer</em>) to simulate think time between user actions.</p>
</li>
<li><p><strong>Use Assertions wisely.</strong> Don’t add extra assertions; focus on key validations such as response time and API status code.</p>
</li>
<li><p><strong>Generate HTML reports using the command below:</strong></p>
<pre><code class="lang-plaintext">  jmeter -n -t test-plan.jmx -l results.jtl -e -o report
</code></pre>
</li>
</ul>
<h3 id="heading-example-folder-structure">Example Folder Structure:</h3>
<p>Follow the folder structure below for an organized test suite.</p>
<pre><code class="lang-plaintext">performance-test/
├── data.csv
├── test-plan.jmx
└── results/
    ├── summary.csv
    └── report.html
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Performance testing is an essential element of a production readiness checklist for any product. It helps you ensure that your product can handle the expected user load and scale gracefully.</p>
<p>This guide is your first step towards writing end-to-end performance test cases and bridging the gap between being a functional test engineer and a full-stack QA Engineer who understands both quality and scalability.</p>
<p>I hope you found this tutorial helpful. If you want to stay connected or learn more about performance testing, follow me on <a target="_blank" href="https://www.linkedin.com/in/mah-noorqa/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Multi-Module Projects in Spring Boot for Scalable Microservices ]]>
                </title>
                <description>
                    <![CDATA[ As software applications grow in complexity, managing scalability, modularity, and clarity becomes essential. Spring Boot’s multi-module structure allows you to manage different parts of the application independently, which lets your team develop, te... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-multi-module-projects-in-spring-boot-for-scalable-microservices/</link>
                <guid isPermaLink="false">6733855c0e235bf7a79c5c4f</guid>
                
                    <category>
                        <![CDATA[ Spring Boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maven ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Birkaran Sachdev ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2024 16:42:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/uyfohHiTxho/upload/716c6610c336976df67b833912170336.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As software applications grow in complexity, managing scalability, modularity, and clarity becomes essential.</p>
<p>Spring Boot’s multi-module structure allows you to manage different parts of the application independently, which lets your team develop, test, and deploy components separately. This structure keeps code organized and modular, making it useful for both microservices and large monolithic systems.</p>
<p>In this tutorial, you’ll build a multi-module Spring Boot project, with each module dedicated to a specific responsibility. You’ll learn how to set up modules, configure inter-module communication, handle errors, implement JWT-based security, and deploy using Docker.</p>
<p><strong>Prerequisites</strong>:</p>
<ul>
<li><p>Basic knowledge of Spring Boot and Maven.</p>
</li>
<li><p>Familiarity with Docker and CI/CD concepts (optional but helpful).</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-1-why-multi-module-projects">Why Multi-Module Projects?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-project-structure-and-architecture">Project Structure and Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-how-to-set-up-the-parent-project">How to Set Up the Parent Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-how-to-create-the-modules">How to Create the Modules</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-inter-module-communication">Inter-Module Communication</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-common-pitfalls-and-solutions">Common Pitfalls and Solutions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-testing-strategy">Testing Strategy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-error-handling-and-logging">Error Handling and Logging</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-9-security-and-jwt-integration">Security and JWT Integration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-10-deployment-with-docker-and-cicd">Deployment with Docker and CI/CD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-11-best-practices-and-advanced-use-cases">Best Practices and Advanced Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-12-conclusion-and-key-takeaways">Conclusion and Key Takeaways</a></p>
</li>
</ol>
<h2 id="heading-1-why-multi-module-projects">1. Why Multi-Module Projects?</h2>
<p>In single-module projects, components are often tightly coupled, making it difficult to scale and manage complex codebases. A multi-module structure offers several advantages:</p>
<ul>
<li><p><strong>Modularity</strong>: Each module is dedicated to a specific task, such as User Management or Inventory, simplifying management and troubleshooting.</p>
</li>
<li><p><strong>Team Scalability</strong>: Teams can work independently on different modules, minimizing conflicts and enhancing productivity.</p>
</li>
<li><p><strong>Flexible Deployment</strong>: Modules can be deployed or updated independently, which is particularly beneficial for microservices or large applications with numerous features.</p>
</li>
</ul>
<h3 id="heading-real-world-example"><strong>Real-World Example</strong></h3>
<p>Consider a large e-commerce application. Its architecture can be divided into distinct modules:</p>
<ul>
<li><p><strong>Customer Management</strong>: Responsible for handling customer profiles, preferences, and authentication.</p>
</li>
<li><p><strong>Product Management</strong>: Focuses on managing product details, stock, and pricing.</p>
</li>
<li><p><strong>Order Processing</strong>: Manages orders, payments, and order tracking.</p>
</li>
<li><p><strong>Inventory Management</strong>: Oversees stock levels and supplier orders.</p>
</li>
</ul>
<h3 id="heading-case-study-netflix"><strong>Case Study: Netflix</strong></h3>
<p>To illustrate these benefits, let's examine how Netflix employs a multi-module architecture.</p>
<p>Netflix is a leading example of a company that effectively uses this approach through its microservices architecture. Each microservice at Netflix is dedicated to a specific function, such as user authentication, content recommendations, or streaming services.</p>
<p>This modular structure enables Netflix to scale its operations efficiently, deploy updates independently, and maintain high availability and performance. By decoupling services, Netflix can manage millions of users and deliver content seamlessly worldwide, ensuring a robust and flexible system that supports its vast and dynamic platform.</p>
<p>This architecture not only enhances scalability but also improves fault isolation, allowing Netflix to innovate rapidly and respond effectively to user demands.</p>
<h2 id="heading-2-project-structure-and-architecture">2. Project Structure and Architecture</h2>
<p>Now let’s get back to our example project. Your multi-module Spring Boot project will use five key modules. Here’s the layout:</p>
<pre><code class="lang-plaintext">codespring-boot-multi-module/
 ├── common/               # Shared utilities and constants
 ├── domain/               # Domain entities
 ├── repository/           # Data access layer (DAL)
 ├── service/              # Business logic
 └── web/                  # Main Spring Boot application and controllers
</code></pre>
<p>Each module has a specific role:</p>
<ul>
<li><p><code>common</code>: Stores shared utilities, constants, and configuration files used across other modules.</p>
</li>
<li><p><code>domain</code>: Contains data models for your application.</p>
</li>
<li><p><code>repository</code>: Manages database operations.</p>
</li>
<li><p><code>service</code>: Encapsulates business logic.</p>
</li>
<li><p><code>web</code>: Defines REST API endpoints and serves as the application’s entry point.</p>
</li>
</ul>
<p>This structure aligns with <strong>separation of concerns</strong> principles, where each layer is independent and handles its own logic.</p>
<p>The diagram below illustrates the various modules:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730873719792/adfc3689-26ae-477a-9850-75070a777e5e.png" alt="Diagram showing a software architecture with five modules: Web, Service, Repository, Domain, and Common, connected by arrows indicating relationships." class="image--center mx-auto" width="1306" height="767" loading="lazy"></p>
<h2 id="heading-3-how-to-set-up-the-parent-project">3. How to Set Up the Parent Project</h2>
<h3 id="heading-step-1-create-the-root-project">Step 1: Create the Root Project</h3>
<p>Let’s run these commands to create the Maven parent project:</p>
<pre><code class="lang-bash">mvn archetype:generate -DgroupId=com.example -DartifactId=spring-boot-multi-module -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=<span class="hljs-literal">false</span>
<span class="hljs-built_in">cd</span> spring-boot-multi-module
</code></pre>
<h3 id="heading-step-2-configure-the-parent-pomxml">Step 2: Configure the Parent <code>pom.xml</code></h3>
<p>In the <code>pom.xml</code>, let’s define our dependencies and modules:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0"</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0 http://www.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.example<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-multi-module<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">packaging</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">packaging</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">modules</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>common<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>domain<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>repository<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>service<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>web<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">modules</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>11<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">spring.boot.version</span>&gt;</span>2.5.4<span class="hljs-tag">&lt;/<span class="hljs-name">spring.boot.version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span>
</code></pre>
<p>This <code>pom.xml</code> file centralizes dependencies and configurations, making it easier to manage shared settings across modules.</p>
<h2 id="heading-4-how-to-create-the-modules">4. How to Create the Modules</h2>
<h3 id="heading-common-module">Common Module</h3>
<p>Let’s create a <strong>common</strong> module to define shared utilities like date formatters. Create this module and add a sample utility class:</p>
<pre><code class="lang-bash">mvn archetype:generate -DgroupId=com.example.common -DartifactId=common -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=<span class="hljs-literal">false</span>
</code></pre>
<p><strong>Date Formatter Utility:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.common;

<span class="hljs-keyword">import</span> java.time.LocalDate;
<span class="hljs-keyword">import</span> java.time.format.DateTimeFormatter;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DateUtils</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">formatDate</span><span class="hljs-params">(LocalDate date)</span> </span>{
        <span class="hljs-keyword">return</span> date.format(DateTimeFormatter.ofPattern(<span class="hljs-string">"yyyy-MM-dd"</span>));
    }
}
</code></pre>
<h3 id="heading-domain-module">Domain Module</h3>
<p>In the <strong>domain</strong> module, you will define your data models.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.domain;

<span class="hljs-keyword">import</span> javax.persistence.Entity;
<span class="hljs-keyword">import</span> javax.persistence.Id;

<span class="hljs-meta">@Entity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-meta">@Id</span>
    <span class="hljs-keyword">private</span> Long id;
    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-comment">// Getters and Setters</span>
}
</code></pre>
<h3 id="heading-repository-module">Repository Module</h3>
<p>Let’s create the <strong>repository</strong> module to manage data access. Here’s a basic repository interface:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.repository;

<span class="hljs-keyword">import</span> com.example.domain.User;
<span class="hljs-keyword">import</span> org.springframework.data.jpa.repository.JpaRepository;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">Long</span>&gt; </span>{}
</code></pre>
<h3 id="heading-service-module">Service Module</h3>
<p>Let’s create the <strong>service</strong> module to hold your business logic. Here’s an example service class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.service;

<span class="hljs-keyword">import</span> com.example.domain.User;
<span class="hljs-keyword">import</span> com.example.repository.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserById</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findById(id).orElse(<span class="hljs-keyword">null</span>);
    }
}
</code></pre>
<h3 id="heading-web-module">Web Module</h3>
<p>The <strong>web</strong> module serves as the REST API layer.</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@GetMapping("/users/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable</span> Long id)</span> </span>{
        <span class="hljs-keyword">return</span> userService.getUserById(id);
    }
}
</code></pre>
<h2 id="heading-5-inter-module-communication">5. Inter-Module Communication</h2>
<p>To avoid direct dependencies, you can use <strong>REST APIs</strong> or <strong>message brokers</strong> (like Kafka) for inter-module communication. This ensures loose coupling and allows each module to communicate independently.</p>
<p>The diagram below demonstrates how modules communicate with each other:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730874358819/89d7f058-d074-4b1d-bbb7-81a7bdcb868e.png" alt="Flowchart showing the interaction between modules in the software architecture: Web Module handles API endpoints and returns responses, Service Module executes business logic, Repository Module accesses data and returns processed data, and connects to a Database." class="image--center mx-auto" width="932" height="1263" loading="lazy"></p>
<p>The diagram illustrates how different system components communicate to handle requests efficiently.</p>
<p>The <strong>Web Module</strong> processes incoming API requests and forwards them to the <strong>Service Module</strong>, which contains the business logic. The <strong>Service Module</strong> then interacts with the <strong>Repository Module</strong> to fetch or update data in the <strong>Database</strong>. This layered approach ensures that each module operates independently, promoting flexibility and easier maintenance.</p>
<p><strong>Example Using Feign Client</strong>:</p>
<p>In the context of inter-module communication, using tools like <strong>Feign Clients</strong> is a powerful way to achieve loose coupling between services.</p>
<p>The Feign client allows one module to seamlessly communicate with another through REST API calls, without requiring direct dependencies. This approach fits perfectly within the layered architecture described earlier, where the <strong>Service Module</strong> can fetch data from other services or microservices using Feign clients, rather than directly accessing databases or hard-coding HTTP requests.</p>
<p>This not only simplifies the code but also improves scalability and maintainability by isolating service dependencies.</p>
<pre><code class="lang-java"><span class="hljs-meta">@FeignClient(name = "userServiceClient", url = "http://localhost:8081")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserServiceClient</span> </span>{
    <span class="hljs-meta">@GetMapping("/users/{id}")</span>
    <span class="hljs-function">User <span class="hljs-title">getUserById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> Long id)</span></span>;
}
</code></pre>
<h2 id="heading-6-common-pitfalls-and-solutions">6. Common Pitfalls and Solutions</h2>
<p>When implementing a multi-module architecture, you may encounter several challenges. Here are some common pitfalls and their solutions:</p>
<ul>
<li><p><strong>Circular Dependencies</strong>: Modules may inadvertently depend on each other, creating a circular dependency that complicates builds and deployments.</p>
<ul>
<li><strong>Solution</strong>: Carefully design module interfaces and use dependency management tools to detect and resolve circular dependencies early in the development process.</li>
</ul>
</li>
<li><p><strong>Over-Engineering</strong>: There's a risk of creating too many modules, leading to unnecessary complexity.</p>
<ul>
<li><strong>Solution</strong>: Start with a minimal set of modules and only split further when there's a clear need, ensuring each module has a distinct responsibility.</li>
</ul>
</li>
<li><p><strong>Inconsistent Configurations</strong>: Managing configurations across multiple modules can lead to inconsistencies.</p>
<ul>
<li><strong>Solution</strong>: Use centralized configuration management tools, such as Spring Cloud Config, to maintain consistency across modules.</li>
</ul>
</li>
<li><p><strong>Communication Overhead</strong>: Inter-module communication can introduce latency and complexity.</p>
<ul>
<li><strong>Solution</strong>: Optimize communication by using efficient protocols and consider asynchronous messaging where appropriate to reduce latency.</li>
</ul>
</li>
<li><p><strong>Testing Complexity</strong>: Testing a multi-module project can be more complex due to the interactions between modules.</p>
<ul>
<li><strong>Solution</strong>: Implement a robust testing strategy that includes unit tests for individual modules and integration tests for inter-module interactions.</li>
</ul>
</li>
</ul>
<p>By being aware of these pitfalls and applying these solutions, you can effectively manage the complexities of a multi-module architecture and ensure a smooth development process.</p>
<h2 id="heading-7-testing-strategy-and-configuration">7. Testing Strategy and Configuration</h2>
<p>Testing each module independently and as a unit is critical in multi-module setups.</p>
<h3 id="heading-unit-tests">Unit Tests</h3>
<p>Here, we’ll use JUnit and Mockito for performing unit tests:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RunWith(MockitoJUnitRunner.class)</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserServiceTest</span> </span>{

    <span class="hljs-meta">@Mock</span>
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-meta">@InjectMocks</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testGetUserById</span><span class="hljs-params">()</span> </span>{
        User user = <span class="hljs-keyword">new</span> User();
        user.setId(<span class="hljs-number">1L</span>);
        user.setName(<span class="hljs-string">"John"</span>);

        Mockito.when(userRepository.findById(<span class="hljs-number">1L</span>)).thenReturn(Optional.of(user));

        User result = userService.getUserById(<span class="hljs-number">1L</span>);
        assertEquals(<span class="hljs-string">"John"</span>, result.getName());
    }
}
</code></pre>
<h3 id="heading-integration-tests">Integration Tests</h3>
<p>And we’ll use Testcontainers with an in-memory database for integration tests:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Testcontainers</span>
<span class="hljs-meta">@ExtendWith(SpringExtension.class)</span>
<span class="hljs-meta">@SpringBootTest</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserServiceIntegrationTest</span> </span>{

    <span class="hljs-meta">@Container</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> PostgreSQLContainer&lt;?&gt; postgresqlContainer = <span class="hljs-keyword">new</span> PostgreSQLContainer&lt;&gt;(<span class="hljs-string">"postgres:latest"</span>);

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testFindById</span><span class="hljs-params">()</span> </span>{
        User user = userService.getUserById(<span class="hljs-number">1L</span>);
        assertNotNull(user);
    }
}
</code></pre>
<h2 id="heading-8-error-handling-and-logging">8. Error Handling and Logging</h2>
<p>Error handling and logging ensure a robust and debuggable application.</p>
<h3 id="heading-error-handling">Error Handling</h3>
<p>In this section, we'll explore how to handle errors gracefully in your Spring Boot application using a <strong>global exception handler</strong>. By using <code>@ControllerAdvice</code>, we'll set up a centralized way to catch and respond to errors, keeping our code clean and our responses consistent.</p>
<pre><code class="lang-java"><span class="hljs-meta">@ControllerAdvice</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GlobalExceptionHandler</span> </span>{

    <span class="hljs-meta">@ExceptionHandler(UserNotFoundException.class)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">handleUserNotFoundException</span><span class="hljs-params">(UserNotFoundException ex)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity&lt;&gt;(<span class="hljs-string">"User not found"</span>, HttpStatus.NOT_FOUND);
    }
}
</code></pre>
<p>In the code example above, we define a <code>GlobalExceptionHandler</code> that catches any <code>UserNotFoundException</code> and returns a friendly message like "User not found" with a status of <code>404</code>. This way, you don’t have to handle this exception in every controller—you’ve got it covered in one place!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730874789550/feed75e6-f92c-4102-b3c3-a01f189f3cd7.png" alt="Flowchart depicting a sequence of interactions between a Client, Web Module, Global Error Handler, and Logger. The process involves handling requests, processing them, and managing exceptions. If an exception occurs, it is handled and logged, followed by an error response. If no exception occurs, a successful response is returned." class="image--center mx-auto" width="1617" height="1350" loading="lazy"></p>
<p>Now, let’s take a look at the diagram. Here’s how it all flows: when a client sends a request to our <strong>Web Module</strong>, if everything goes smoothly, you'll get a successful response. But if something goes wrong, like a user not being found, the error will be caught by our <strong>Global Error Handler</strong>. This handler logs the issue and returns a clean, structured response to the client.</p>
<p>This approach ensures that users get clear error messages while keeping your app’s internals hidden and secure.</p>
<h3 id="heading-logging">Logging</h3>
<p>Structured logging in each module improves traceability and debugging. You can use a centralized logging system like Logback and include correlation IDs to trace requests.</p>
<h2 id="heading-9-security-and-jwt-integration">9. Security and JWT Integration</h2>
<p>In this section, we’re going to set up <strong>JSON Web Tokens (JWT)</strong> to secure our endpoints and control access based on user roles. We'll configure this in the <code>SecurityConfig</code> class, which will help us enforce who can access what parts of our application.</p>
<pre><code class="lang-java"><span class="hljs-meta">@EnableWebSecurity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WebSecurityConfigurerAdapter</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        http.authorizeRequests()
            .antMatchers(<span class="hljs-string">"/admin/**"</span>).hasRole(<span class="hljs-string">"ADMIN"</span>)
            .antMatchers(<span class="hljs-string">"/user/**"</span>).hasAnyRole(<span class="hljs-string">"USER"</span>, <span class="hljs-string">"ADMIN"</span>)
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer().jwt();
    }
}
</code></pre>
<p>In the code example above, you can see how we’ve defined access rules:</p>
<ul>
<li><p>The <code>/admin/**</code> endpoints are restricted to users with the <code>ADMIN</code> role.</p>
</li>
<li><p>The <code>/user/**</code> endpoints can be accessed by users with either the <code>USER</code> or <code>ADMIN</code> roles.</p>
</li>
<li><p>Any other requests will require the user to be authenticated.</p>
</li>
</ul>
<p>Next, we set up our application to validate incoming tokens using <code>.oauth2ResourceServer().jwt();</code>. This ensures that only requests with a valid token can access our secured endpoints.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730875088355/b0502e8e-88e4-4aab-bf52-81360892ffbb.png" alt="Diagram depicting a sequence of interactions among five components: Client, Web Module, Security Filter, Service, and Repository. Arrows represent steps for token authentication and accessing a service, including requests, validations, data fetching, and responses, with outcomes for both valid and invalid tokens." class="image--center mx-auto" width="2012" height="1531" loading="lazy"></p>
<p>Now, let’s walk through the diagram. When a client sends a request to access a resource, the <strong>Security Filter</strong> first checks if the provided JWT token is valid. If the token is valid, the request proceeds to the <strong>Service Module</strong> to fetch or process the data. If not, access is denied right away, and the client receives an error response.</p>
<p>This flow ensures that only authenticated users can access sensitive resources, keeping our application secure.</p>
<h2 id="heading-10-deployment-with-docker-and-cicd">10. Deployment with Docker and CI/CD</h2>
<p>In this section, we'll containerize each module using <strong>Docker</strong> to make our application easier to deploy and run consistently across different environments. We’ll also set up a <strong>CI/CD pipeline</strong> using GitHub Actions (but you can use Jenkins too if you prefer). Automating this process ensures that any changes you push are automatically built, tested, and deployed.</p>
<h3 id="heading-step-1-containerizing-with-docker">Step 1: Containerizing with Docker</h3>
<p>We start by creating a <strong>Dockerfile</strong> for the <strong>Web Module:</strong></p>
<pre><code class="lang-java">FROM openjdk:<span class="hljs-number">11</span>-jre-slim
COPY target/web-<span class="hljs-number">1.0</span>-SNAPSHOT.jar app.jar
ENTRYPOINT [<span class="hljs-string">"java"</span>, <span class="hljs-string">"-jar"</span>, <span class="hljs-string">"/app.jar"</span>]
</code></pre>
<p>Here, we’re using a lightweight version of Java 11 to keep our image size small. We copy the compiled <code>.jar</code> file into the container and set it up to run when the container starts.</p>
<h3 id="heading-step-2-using-docker-compose-for-multi-module-deployment">Step 2: Using Docker Compose for Multi-Module Deployment</h3>
<p>Now, we'll use a <strong>Docker Compose</strong> file to orchestrate multiple modules together:</p>
<pre><code class="lang-java">version: <span class="hljs-string">'3'</span>
services:
  web:
    build: ./web
    ports:
      - <span class="hljs-string">"8080:8080"</span>
  service:
    build: ./service
    ports:
      - <span class="hljs-string">"8081:8081"</span>
</code></pre>
<p>With this setup, we can run both the <strong>Web Module</strong> and the <strong>Service Module</strong> at the same time, making it easy to spin up the entire application with a single command. Each service is built separately from its own directory, and we expose the necessary ports to access them.</p>
<h3 id="heading-cicd-example-with-github-actions">CI/CD Example with GitHub Actions</h3>
<pre><code class="lang-java">name: CI Pipeline

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout<span class="hljs-meta">@v2</span>
    - name: Set up JDK <span class="hljs-number">11</span>
      uses: actions/setup-java<span class="hljs-meta">@v2</span>
      with:
        java-version: <span class="hljs-string">'11'</span>
    - name: Build with Maven
      run: mvn clean install
</code></pre>
<p>This pipeline automatically kicks in whenever you push new code or create a pull request. It checks out your code, sets up Java, and runs a Maven build to ensure everything is working correctly.</p>
<h2 id="heading-11-best-practices-and-advanced-use-cases">11. Best Practices and Advanced Use Cases</h2>
<p>The following best practices ensure maintainability and scalability.</p>
<h3 id="heading-best-practices">Best Practices</h3>
<ul>
<li><p><strong>Avoid Circular Dependencies</strong>: Ensure modules don’t have circular references to avoid build issues.</p>
</li>
<li><p><strong>Separate Concerns Clearly</strong>: Each module should focus on one responsibility.</p>
</li>
<li><p><strong>Centralized Configurations</strong>: Manage configurations centrally for consistent setups.</p>
</li>
</ul>
<h3 id="heading-advanced-use-cases">Advanced Use Cases</h3>
<ol>
<li><p><strong>Asynchronous Messaging with Kafka</strong>: Use Kafka for decoupled communication between services. Modules can publish and subscribe to events asynchronously.</p>
</li>
<li><p><strong>REST Client with Feign</strong>: Use Feign to call services within modules. Define a Feign client interface for communication.</p>
</li>
<li><p><strong>Caching for Performance</strong>: Use Spring Cache in the service module for optimizing data retrieval.</p>
</li>
</ol>
<h2 id="heading-conclusion-and-key-takeaways">Conclusion and Key Takeaways</h2>
<p>A multi-module Spring Boot project provides modularity, scalability, and ease of maintenance.</p>
<p>In this tutorial, you learned to set up modules, manage inter-module communication, handle errors, add security, and deploy with Docker.</p>
<p>Following best practices and using advanced techniques like messaging and caching will further optimize your multi-module architecture for production use.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Effectively Manage Unique Identifiers at Scale: From GUIDs to Snowflake IDs and Other Modern Solutions ]]>
                </title>
                <description>
                    <![CDATA[ What Are Unique Identifiers? 🪪 Unique identifiers (UIDs) are crucial components in software engineering and data management. They serve as distinct references for entities within a system and ensure that each item – whether a database record, a user... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-effectively-manage-unique-identifiers-at-scale/</link>
                <guid isPermaLink="false">66c4dea5fd5e7dd1b40d4a81</guid>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unique identifier ]]>
                    </category>
                
                    <category>
                        <![CDATA[ guid ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gor Grigoryan ]]>
                </dc:creator>
                <pubDate>Tue, 20 Aug 2024 18:21:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724012658962/2e754dc4-248a-4a2b-8819-993514474a22.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-are-unique-identifiers">What Are Unique Identifiers? 🪪</h2>
<p>Unique identifiers (UIDs) are crucial components in software engineering and data management. They serve as distinct references for entities within a system and ensure that each item – whether a database record, a user, or a file – can be uniquely identified and accessed.</p>
<p>UIDs are critical for maintaining data, enabling efficient search and retrieval, and supporting large-scale operations in distributed systems. As data volumes and system complexities grow, the need for scalable UID solutions becomes increasingly important.</p>
<p>In this article, you'll learn all about the history of unique identifiers, as well as how some modern solutions work.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><p><a class="post-section-overview" href="#introduction-to-unique-identifiers-">Introduction to Unique Identifiers 🪪</a></p>
<ul>
<li><p><a class="post-section-overview" href="#the-historical-context-of-identifiers">The Historical Context of Identifiers</a></p>
</li>
<li><p><a class="post-section-overview" href="#government-management-of-unique-identifiers">Government Management of Unique Identifiers</a></p>
</li>
<li><p><a class="post-section-overview" href="#structure-of-social-security-numbers">Structure of Social Security Numbers</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#scalability-in-government-systems">Scalability in Government Systems</a></p>
<ul>
<li><p><a class="post-section-overview" href="#tech-companies-and-their-scale">Tech Companies and Their Scale</a></p>
</li>
<li><p><a class="post-section-overview" href="#meta-facebook-">Meta (Facebook)</a></p>
</li>
<li><p><a class="post-section-overview" href="#x-twitter-">X (Twitter)</a></p>
</li>
<li><p><a class="post-section-overview" href="#telegram">Telegram</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#the-role-of-auto-increment-ids-and-their-scalability-issues">The Role of Auto-increment IDs and Their Scalability Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#sequence-numbers-and-their-advantages-over-auto-increment-ids">Sequence Numbers and Their Advantages Over Auto-increment IDs</a></p>
</li>
<li><p><a class="post-section-overview" href="#uuids-overview-and-usage">UUIDs: Overview and Usage</a></p>
<ul>
<li><p><a class="post-section-overview" href="#what-s-so-great-about-uuids">What's so great about UUIDs?</a></p>
</li>
<li><p><a class="post-section-overview" href="#uuid-version-1">UUID Version 1</a></p>
</li>
<li><p><a class="post-section-overview" href="#uuid-version-4">UUID Version 4</a></p>
</li>
<li><p><a class="post-section-overview" href="#uuid-version-5">UUID Version 5</a></p>
</li>
<li><p><a class="post-section-overview" href="#uuid-version-7">UUID Version 7</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-uuid-version-2-3-and-6">UUID Version 2, 3, and 6</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#snowflake-id">Snowflake ID</a></p>
<ul>
<li><p><a class="post-section-overview" href="#the-problem-stated-by-twitter-">"The Problem" stated by twitter:</a></p>
</li>
<li><p><a class="post-section-overview" href="#finding-tweet-timestamps">Finding Tweet Timestamps</a></p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-the-historical-context-of-identifiers">The Historical Context of Identifiers</h3>
<p>The concept of unique identifiers has enveloped significantly over time, reflecting the growing complexity and scale of human societies and technological systems. To understand why unique identifiers are so important today, let’s look at how we've historically managed identification and how it was developed.</p>
<p>In early human societies, individuals were often identified by a <strong>single name</strong>. This was usually sufficient in small communities where everyone knew each other personally. But as populations grew, it became necessary to distinguish between individuals who shared the same first name. This led to the adoption of <strong>surnames</strong>.</p>
<p>For example, in Armenia 🇦🇲, surnames are used to identify individuals by their family or ancestry. Take the example of a person named Gor. In a small group of up to 50 people, let's say, identifying Gor by his first name alone is easy.</p>
<p>But as the group grows to a larger community of, say, 500 people, additional identifiers become necessary. Gor will be identified as Gor Grigoryan, indicating that he belongs to the Grigoryan family/ancestry. This surname provides a clearer identification and connects Gor to his family's lineage.</p>
<p>As societies continued to expand and bureaucratic systems became more complex, even surnames proved not enough for uniquely identifying individuals. This was especially true in larger cities and for the administration of government services. The need for more robust identification methods became apparent.</p>
<h3 id="heading-government-management-of-unique-identifiers">Government Management of Unique Identifiers</h3>
<p>The introduction of passports in the early 20th century marked a significant step in this direction. Passports included unique personal identifiers, such as passport numbers, to distinguish between individuals clearly. These unique IDs ensured that each person could be accurately identified, regardless of name similarities or other ambiguities.</p>
<p>Several countries pioneered the use of unique personal identification numbers to address this need:</p>
<ul>
<li><p><strong>Germany</strong> 🇩🇪: In the 19th century, Germany implemented a system for tracking individuals for social welfare and military conscription purposes.</p>
</li>
<li><p><strong>Sweden</strong> 🇸🇪: Sweden began issuing personal identification numbers (Personnummer) in the 1940s, providing each citizen with a unique identifier for use in various administrative processes.</p>
</li>
<li><p><strong>France</strong> 🇫🇷: France introduced the National Identification Number (Numéro de Sécurité Sociale) in the mid-20th century to streamline social security administration and other government services.</p>
</li>
<li><p><strong>United States</strong> 🇺🇸: The USA followed with the introduction of Social Security Numbers (SSNs) in 1936 as part of the Social Security Act. This approach to unique identification has since been adopted worldwide, with countries issuing national identification numbers to their citizens.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-49.png" alt="image-49" width="600" height="400" loading="lazy"></p>
<p>Information page, Edwin James Tharp’s passport, March 27, 1936, <a target="_blank" href="https://library.csun.edu/SCA/Peek-in-the-Stacks/identities">Robert and Eva Tharp Collection</a>.</p>
<p>As illustrated in the example image, the 1936 UK 🇬🇧 passport included detailed personal information such as eye color, hair color, profession, height, and information about the holder’s spouse and children.</p>
<h3 id="heading-structure-of-social-security-numbers">Structure of Social Security Numbers</h3>
<p>A Social Security Number (SSN) in the United States is a nine-digit number formatted as "AAA-GG-SSSS". Each part of the SSN has historically carried specific information:</p>
<ol>
<li><p><strong>Area Number (AAA)</strong>: Originally, the first three digits, known as the area number, represented the geographical region where the SSN was issued. This regional assignment helped to ensure a systematic distribution of numbers across the country.</p>
</li>
<li><p><strong>Group Number (GG)</strong>: The middle two digits, called the group number, were used to organize the numbers within a given area. The group numbers ranged from 01 to 99 and were issued in a specific order to prevent duplicate numbers within the same area.</p>
</li>
<li><p><strong>Serial Number (SSSS)</strong>: The last four digits are the serial number, which sequentially identifies each individual within a group. This part of the SSN ensures that even if the area and group numbers are the same, the overall SSN remains unique.</p>
</li>
</ol>
<p>The Social Security Administration (SSA) has implemented several measures to ensure that each SSN is unique for the entire USA population (<strong>341.9 million people).</strong></p>
<p>Governments around the world manage unique identifiers primarily for administrative purposes, such as social security, taxation, and national identification. These systems are designed to handle large populations and ensure that every citizen has a unique identifier for official records.</p>
<p>For example, the United States 🇺🇸 Social Security Administration (SSA) manages Social Security Numbers (SSNs) for over 330 million people. Similarly, the Indian 🇮🇳 government has issued Aadhaar numbers, a 12-digit unique identifier, to over <strong>1.3 billion citizens</strong>. These identifiers are crucial for accessing government services, benefits, and other official processes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-52.png" alt="image-52" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Aadhaar">Aadhaar is the world's largest biometric ID system</a> described as "the most sophisticated ID program in the world".</p>
<h2 id="heading-scalability-in-government-systems">Scalability in Government Systems</h2>
<p>While government systems are large, they generally do not face the same scalability challenges as tech companies. Government databases are often centralized, and the rate at which new identifiers are issued is relatively steady and predictable. Also, the frequency of updates and interactions with these identifiers is lower compared to the dynamic environment of tech companies.</p>
<p>Tech companies, especially social media giants, operate on an entirely different scale. These companies manage billions of users and generate vast amounts of data daily. For instance, Meta (formerly Facebook) has over 3 billion monthly active users across its platforms, including Facebook, Instagram, and WhatsApp.</p>
<h3 id="heading-tech-companies-and-their-scale">Tech Companies and Their Scale</h3>
<p>Let's take a few examples:</p>
<h4 id="heading-meta-facebook">Meta (Facebook)</h4>
<ol>
<li><p><strong>User Base</strong>: With over <strong>3 billion monthly active users</strong>, Meta needs a robust system to ensure that each user is uniquely identified.</p>
</li>
<li><p><strong>Posts and Interactions</strong>: Facebook alone sees approximately <strong>350 million new posts daily</strong>. Each of these posts, along with comments, likes, and shares require a unique identifier to manage interactions efficiently.</p>
</li>
<li><p><strong>Messages</strong>: WhatsApp users send around <strong>100 billion messages every day</strong>, each needing a unique identifier to ensure messages are correctly routed and stored.</p>
</li>
<li><p><strong>Unique Data Rows</strong>: With the combination of user profiles, posts, comments, likes, and messages, Meta likely manages over <strong>10+ trillion unique data rows</strong>. (If the global population is approximately 8 billion people, then 10 trillion people would be about <strong>1,250</strong> times the current global population).</p>
</li>
</ol>
<h4 id="heading-x-twitter">X (Twitter)</h4>
<p>Twitter, another social media giant, has about <strong>450 million monthly active users</strong>. On average, users send around <strong>500 million tweets per day</strong>. Each tweet, reply, and retweet needs a unique identifier to maintain the platform's integrity and usability.</p>
<h4 id="heading-telegram">Telegram</h4>
<p>Telegram is known for its high-traffic and robust messaging platform. With over <strong>700 million monthly active users</strong>, Telegram experiences particularly high traffic spikes during events like New Year's Eve, where users send billions of messages within a short timeframe.</p>
<p>On a typical day, Telegram handles over <strong>70 billion messages</strong>. Each message, channel post, and group interaction requires a unique identifier to ensure proper delivery and organization.</p>
<p>The scale at which tech companies operate requires sophisticated and highly scalable unique identifier systems. These systems must handle high concurrency, support distributed architectures, and ensure low latency.</p>
<h2 id="heading-the-role-of-auto-increment-ids-and-their-scalability-issues">The Role of Auto-increment IDs and Their Scalability Issues</h2>
<p>Auto-increment IDs are a common method for generating unique identifiers in relational databases. When a new record is added to a table, the database automatically assigns the next available integer value to the ID field. This method is straightforward and ensures that each record within a table has a unique identifier without requiring any manual intervention.</p>
<p>Consider a table for storing user information in a relational database. When the first user is added, they might be assigned an ID of 1. The second user would receive an ID of 2, and so on.</p>
<p>While auto-increment IDs are simple and effective for small-scale applications, they face significant challenges in larger, distributed systems.</p>
<ol>
<li><p><strong>Concurrency Issues</strong>: In high-traffic applications, multiple transactions might attempt to insert records simultaneously. Ensuring that each transaction receives a unique auto-increment ID can lead to performance bottlenecks and require complex locking mechanisms.</p>
</li>
<li><p><strong>Distributed Systems</strong>: In distributed databases, where data is spread across multiple servers, maintaining a global sequence for auto-increment IDs becomes problematic. Each server would need to coordinate with others to avoid generating duplicate IDs, which can significantly impact performance and reliability.</p>
</li>
<li><p><strong>Single Point of Failure</strong>: Relying on a central authority to generate auto-increment IDs introduces a single point of failure. If the server responsible for assigning IDs goes down, the entire system might be unable to add new records.</p>
</li>
<li><p><strong>Predictability</strong>: Auto-increment IDs are predictable. If someone knows the ID of one record, they can infer the IDs of subsequent records. This predictability can be a security concern in certain applications, such as those involving financial transactions or sensitive user data.</p>
</li>
</ol>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Admins (
    <span class="hljs-keyword">Id</span> <span class="hljs-built_in">SERIAL</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    <span class="hljs-keyword">Name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>
);

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">Users</span> (
    <span class="hljs-keyword">Id</span> <span class="hljs-built_in">SERIAL</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    <span class="hljs-keyword">Name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Admins (<span class="hljs-keyword">Name</span>)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-string">'GorGrigoryan'</span>),
       (<span class="hljs-string">'GorGrigoryan2'</span>);

<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> Admins;


<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | Id | Name          |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 1  | GorGrigoryan  |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 2  | GorGrigoryan2 |</span>
<span class="hljs-comment">-- +----+---------------+</span>
</code></pre>
<h2 id="heading-sequence-numbers-and-their-advantages-over-auto-increment-ids">Sequence Numbers and Their Advantages Over Auto-increment IDs</h2>
<p>Sequence numbers are a method of generating unique identifiers by maintaining a counter that is incremented with each new record. Unlike auto-increment IDs, which are typically limited to a single database instance, sequence numbers can be designed to work across distributed systems, addressing some of the scalability and concurrency issues associated with auto-increment IDs.</p>
<p>How sequence numbers work:</p>
<ol>
<li><p><strong>Centralized Sequence Generators</strong>: A central service or database table generates and manages the sequence numbers. Each request for a new identifier increments the counter and returns the next value.</p>
</li>
<li><p><strong>Distributed Sequence Generators</strong>: In a distributed environment, sequence numbers can be generated by dividing the range of possible values among different nodes or using more complex algorithms to ensure uniqueness without central coordination.</p>
</li>
</ol>
<p>Consider a distributed database system with multiple nodes, each responsible for generating unique sequence numbers. The system might allocate ranges of sequence numbers to each node, ensuring that they can generate identifiers independently:</p>
<ul>
<li><p><strong>Node 1</strong>: Allocated sequence numbers 1,000,000 to 1,999,999</p>
</li>
<li><p><strong>Node 2</strong>: Allocated sequence numbers 2,000,000 to 2,999,999</p>
</li>
<li><p><strong>Node 3</strong>: Allocated sequence numbers 3,000,000 to 3,999,999</p>
</li>
</ul>
<p>Each node can now generate up to one million unique identifiers without needing to communicate with a central server. This approach improves scalability and performance, particularly in environments with high write loads.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">SEQUENCE</span> UserIdentifier
<span class="hljs-keyword">INCREMENT</span> <span class="hljs-number">1</span>
<span class="hljs-keyword">START</span> <span class="hljs-number">1</span>;

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Admins (
    <span class="hljs-keyword">Id</span> <span class="hljs-built_in">INT</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    <span class="hljs-keyword">Name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>
);

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">Users</span> (
    <span class="hljs-keyword">Id</span> <span class="hljs-built_in">INT</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    <span class="hljs-keyword">Name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>
);


<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Admins (<span class="hljs-keyword">Id</span>, <span class="hljs-keyword">Name</span>)
<span class="hljs-keyword">VALUES</span>(<span class="hljs-keyword">nextval</span>(<span class="hljs-string">'UserIdentifier'</span>), <span class="hljs-string">'GorGrigoryan'</span>),
(<span class="hljs-keyword">nextval</span>(<span class="hljs-string">'UserIdentifier'</span>), <span class="hljs-string">'GorGrigoryan2'</span>);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-keyword">Users</span> (<span class="hljs-keyword">Id</span>, <span class="hljs-keyword">Name</span>)
<span class="hljs-keyword">VALUES</span>(<span class="hljs-keyword">nextval</span>(<span class="hljs-string">'UserIdentifier'</span>), <span class="hljs-string">'UserGorGrigoryan'</span>),
(<span class="hljs-keyword">nextval</span>(<span class="hljs-string">'UserIdentifier'</span>), <span class="hljs-string">'UserGorGrigoryan2'</span>);


<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> Admins;

<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | Id | Name          |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 1  | GorGrigoryan  |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 2  | GorGrigoryan2 |</span>
<span class="hljs-comment">-- +----+---------------+</span>

<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">Users</span>;

<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | Id | Name          |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 3  | GorGrigoryan  |</span>
<span class="hljs-comment">-- +----+---------------+</span>
<span class="hljs-comment">-- | 4  | GorGrigoryan2 |</span>
<span class="hljs-comment">-- +----+---------------+</span>
</code></pre>
<p>Another advantage of using sequence numbers is that you can obtain the ID of the entity before it is inserted into the database.</p>
<p>In the case of auto-increment IDs, this assignment is typically handled by the database upon insertion, which can limit flexibility. With sequence numbers, you can easily generate the ID on the application side, which can be an easy task when using some ORMs e.g the EF Core ORM in C#</p>
<p>Check out sequence numbers on the SQL server <a target="_blank" href="https://learn.microsoft.com/en-us/sql/relational-databases/sequence-numbers/sequence-numbers?view=sql-server-ver16">here</a>.</p>
<h2 id="heading-uuids-overview-and-usage">UUIDs: Overview and Usage</h2>
<p>GUIDs (Globally Unique Identifiers), also known as UUIDs (Universally Unique Identifiers), are 128-bit identifiers designed to be globally unique. A typical UUID is displayed in a 32-character hexadecimal string, divided into five groups separated by hyphens. For example: <code>126e3456-e89b-12d3-a456-426614174000</code>.</p>
<h3 id="heading-whats-so-great-about-uuids">What's so great about UUIDs?</h3>
<p>One of the standout features of GUIDs is their huge capacity for uniqueness. With a 128-bit structure, the total number of possible GUIDs is very large: Specifically, there are <code>340,282,366,920,938,463,463,374,607,431,770,000,000</code> GUIDs available. To put that into perspective, let's compare it with something tangible.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-94.png" alt="image-94" width="600" height="400" loading="lazy"></p>
<p>Did you know that scientists have attempted to calculate the number of grains of sand on Earth? Science writer David Blatner, in his book <a target="_blank" href="https://www.amazon.com/Spectrums-Mind-boggling-Universe-Infinitesimal-Infinity/dp/1620405202">Spectrums</a>, mentions that a group of researchers at the University of Hawaii tried to estimate this number. They determined that Earth has roughly (and we are speaking very roughly) 7.5 x 10<sup>18</sup> grains of sand, or seven quintillion, five hundred quadrillion grains. For more, consider reading the article titled: "<a target="_blank" href="https://www.npr.org/sections/krulwich/2012/09/17/161096233/which-is-greater-the-number-of-sand-grains-on-earth-or-stars-in-the-sky"><strong>Which Is Greater, The Number Of Sand Grains On Earth Or Stars In The Sky?</strong></a><strong>"</strong></p>
<p>Now, to compare those numbers:</p>
<pre><code class="lang-sql">| GUIDs available | 340,282,366,920,938,463,463,374,607,431,770,000,000
| Sand grains     | 75,000,000,000,000,000,000
</code></pre>
<p>If you decided to create an application to track every grain of sand on Earth and assign each a unique identifier, you could easily do that using GUIDs. The fun part is that you could actually repeat this process <code>4,537,098,225,612,512,846</code> times over without running out of unique GUIDs! 🤯</p>
<h3 id="heading-uuid-version-1">UUID Version 1</h3>
<p>UUID Version 1 generates unique identifiers based on the current timestamp, clock sequence, and node identifier (typically the MAC address of the machine generating the UUID).</p>
<p>According to <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc4122">RFC 4122</a>, the timestamp is the number of nanoseconds since October 15, 1582, at midnight UTC. Most computers do not have a clock that ticks fast enough to measure time in nanoseconds. Instead, a random number is often used to fill in timestamp digits beyond the computer's measurement accuracy.</p>
<p>When multiple version-1 UUIDs are generated in a single API call, the random portion may be incremented rather than regenerated for each UUID. This ensures uniqueness and is faster to generate.</p>
<p>UUID v1 also has the mac address attached to it. By including a MAC address in the UUID, you can be sure that two different computers will never generate the same UUID. Because MAC addresses are globally unique, but also note that version-1 UUIDs can be traced back to the computer that generated them.</p>
<p>This ensures that the UUID is unique across both time and space. It is suitable when the <strong>generation time and machine uniqueness</strong> are important. It is often used in systems where the timestamp of creation is relevant or needed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-95.png" alt="image-95" width="600" height="400" loading="lazy"></p>
<p>(Image from <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc4122">here</a>)</p>
<h3 id="heading-uuid-version-4">UUID Version 4</h3>
<p>UUID Version 4 generates identifiers using random or pseudo-random numbers. This method ensures a high probability of uniqueness due to the vast number of possible GUIDs. This is the most common UUID version.</p>
<p>There are 2 main variants of UUID:</p>
<ul>
<li><p>Variant 1: <a target="_blank" href="https://minecraft.fandom.com/wiki/Universally_unique_identifier">Minecraft UUID</a>, also called Timestamp-first UUIDs</p>
</li>
<li><p>Variant 2:  "GUID"</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-96.png" alt="image-96" width="600" height="400" loading="lazy"></p>
<p>(<a target="_blank" href="https://www.uuidtools.com/minecraft">Image from here</a>)</p>
<p>GUID is entirely random, making it simple to generate and ensuring that each identifier is unique with a very high probability. The unique identifiers are made up of 128 bits. They are written as 32 characters using numbers (0-9) and letters (A-F). The characters are grouped in a specific format: 8-4-4-4-12, separated by hyphens, like this: <code>{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}</code>.</p>
<p>The great thing about GUIDs is that you don’t need a central system to create them. Anyone can generate a GUID using an algorithm, and it will still be unique across different systems and applications. They are designed to be used nearly everywhere a unique identifier is needed. Here are some usage examples:</p>
<ul>
<li><p>Windows: Uses GUIDs to generate unique product keys</p>
</li>
<li><p>Microsoft SQL Server: Uses GUIDs as primary keys to ensure global uniqueness across distributed databases</p>
</li>
<li><p>AWS: Uses GUIDs for uniquely identifying resources in their cloud infrastructure, such as EC2 instances and S3 objects</p>
</li>
<li><p>eBay: Uses GUIDs to identify listings, transactions, and users</p>
</li>
</ul>
<h3 id="heading-uuid-version-5">UUID Version 5</h3>
<p>UUID Version 5 generates unique identifiers based on a <strong>namespace</strong> identifier and a <strong>name</strong>. The namespace and name are combined and hashed using SHA-1 to produce the UUID. This ensures that the same namespace and name combination will always produce the same UUID. In UUID, the namespace must be a UUID, and the name can be anything.</p>
<p>UUID V5 is useful for generating consistent unique identifiers for the same input data across different systems and contexts. Let's say we want to generate a user id based on their username. Here’s how you can achieve this in C#:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-97.png" alt="image-97" width="600" height="400" loading="lazy"></p>
<p>Here the UUID Version 5 solves several important problems, particularly when you need a consistent and unique identifier based on a given input.</p>
<p>For instance, consider a scenario where you need a user ID to make an API call (or anything else), but in your code, you only have the username accessible. How would the problem be solved if we were using UUID Version 4 (GUIDs)? Most likely, it would work something like this:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">/* When using GUID (UUID v4) */</span>

<span class="hljs-keyword">var</span> userName = <span class="hljs-string">"bob"</span>; <span class="hljs-comment">// Lets assume we only have username</span>
<span class="hljs-comment">// API call or DB call to get the user id using name</span>
<span class="hljs-keyword">var</span> userId = <span class="hljs-keyword">await</span> userService.GetUserIdAsync(userName);

<span class="hljs-keyword">await</span> userService.ChangeUserNameAsync(userId, <span class="hljs-string">"bob-2"</span>);
</code></pre>
<p>By using UUID Version 5 with a shared namespace across all your projects, you can easily generate the user ID from the username without making any additional API calls. So the same code would look like this:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">/* When using UUID v5 */</span>

<span class="hljs-comment">// From some shared code</span>
<span class="hljs-keyword">var</span> userNamespace = SharedConstants.UserNamespace;

<span class="hljs-keyword">var</span> userName = <span class="hljs-string">"bob"</span>; <span class="hljs-comment">// Lets assume we only have username</span>

<span class="hljs-comment">//Generate the user id in place, without additional call</span>
<span class="hljs-keyword">var</span> userId = Uuid.NewNameBased(userNamespace, userName);

<span class="hljs-keyword">await</span> userService.ChangeUserNameAsync(userId, <span class="hljs-string">"bob-2"</span>);
</code></pre>
<p>This approach eliminates the need for redundant API calls. In a distributed system, making an API call to fetch a user ID every time you need it can be inefficient and slow. With UUID Version 5, you can locally generate the user ID from the username (or any other input), reducing the need for network requests and significantly improving the efficiency of your application.</p>
<p>What kind of problem have we solved with UUID v5? Let's say you need a user ID to make an API call but in your code, you have only a username, if you have the namespace shared across all your projects. Then you can easily get the user id using a username, without making any API call. That's because UUID v5 always reproduces the same UUID for the same input.</p>
<p>Also, UUID Version 5 ensures uniqueness and consistency across different systems. When integrating multiple systems or microservices, it can be challenging to keep user IDs consistent across various services. By using the same namespace and the same input (such as a username), UUID Version 5 guarantees that the generated IDs are unique and consistent across all systems, facilitating smoother integration and data consistency.</p>
<h3 id="heading-uuid-version-7">UUID Version 7</h3>
<p>GUID Version 7 is a proposed new version that aims to combine the strengths of both timestamp-based and random-based GUIDs.</p>
<h4 id="heading-problems-with-uuid-v4-guid"><strong>Problems with UUID v4 (GUID)</strong></h4>
<p>UUID Version 4 generates non-time-ordered values, meaning the identifiers created are not sequential. Since these values are randomly generated, they won't be clustered together in a database index. Instead, inserts will occur at random locations, which can negatively impact the performance of common index data structures, such as B-trees and their variants.</p>
<p>In a scenario where your product requires <em>frequent access to recent data</em>, non-sequential identifiers create a significant challenge.</p>
<p>With UUID Version 4, the most recent data will be inserted randomly throughout the index, <em>lacking clustering</em>. As a result, retrieving the most recent data from a large dataset requires traversing numerous database index pages.</p>
<p>In contrast, using sequential identifiers ensures that the latest data is logically arranged at the right-most part of the index, making it much more cache-friendly. This organization allows for faster and more efficient retrieval of recent data, as it minimizes the number of index pages that need to be accessed which is a lack in UUID v4.</p>
<h4 id="heading-the-solution-with-uuid-v7"><strong>The solution with UUID v7</strong></h4>
<p>UUID v7 is designed to provide unique and sortable identifiers that are both easy to generate and useful for distributed systems. It uses a combination of timestamps and random data to ensure both uniqueness and temporal order.</p>
<p>The first part of the UUID is a timestamp that provides a chronological component, ensuring that UUIDs generated close together in time are also close together in value. The remaining part is filled with random data, ensuring the uniqueness of each identifier.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-98.png" alt="image-98" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://buildkite.com/blog/goodbye-integers-hello-uuids">Buildkite post about migrating to UUID v7</a></p>
<h3 id="heading-uuid-versions-2-3-and-6">UUID Versions 2, 3, and 6</h3>
<p>You may have noticed that our discussion focuses on UUID Versions 1, 4, 5, and 7, and skips over Versions 2, 3, and 6. Here's why:</p>
<ul>
<li><p><strong>UUID Version 2</strong>: This version is rarely used in modern applications. It’s similar to Version 1 but includes additional fields for things like domain information (such as POSIX UID or GID). It was mainly used in legacy systems and is now considered largely obsolete.</p>
</li>
<li><p><strong>UUID Version 3</strong>: This version is based on a name and a namespace, similar to Version 5. The main difference is that Version 3 uses the MD5 hashing algorithm, which is less secure and less efficient than the SHA-1 algorithm used in Version 5. Version 5 is generally preferred because SHA-1 is more robust.</p>
</li>
<li><p><strong>UUID Version 6</strong>: Version 6 is still under draft as a proposed standard. It is meant to provide a time-ordered UUID with better performance for distributed systems, but since it hasn't been fully adopted yet, we focus on Version 7, which offers similar features and has more momentum.</p>
</li>
</ul>
<h2 id="heading-snowflake-id">Snowflake ID</h2>
<p>Snowflake ID is a unique identifier generation system developed by Twitter to address the challenges of generating unique, sequential, and distributed identifiers in a highly scalable and efficient manner.</p>
<p>Unlike GUIDs, which are often non-sequential and can cause performance issues in database indexing, Snowflake IDs are designed to be both time-ordered and globally unique, making them ideal for distributed systems and databases where sequential order is important.</p>
<p>A Snowflake ID is a 64-bit integer composed of several distinct parts:</p>
<ol>
<li><p><strong>Timestamp (41 bits):</strong> The largest portion of the Snowflake ID is the timestamp, which records the number of milliseconds since a custom epoch (often set to the date when the system was first deployed). This ensures that IDs are time-ordered and can be easily sorted based on their creation time.</p>
</li>
<li><p><strong>Datacenter ID (5 bits):</strong> This part of the ID identifies the datacenter where the ID was generated, allowing the system to generate unique IDs across multiple data centers without conflicts.</p>
</li>
<li><p><strong>Machine ID (5 bits):</strong> Similar to the datacenter ID, the machine ID identifies the specific server or machine within the datacenter that generated the ID. This ensures that even within the same data center, IDs remain unique.</p>
</li>
<li><p><strong>Sequence Number (12 bits):</strong> The sequence number is used to differentiate between multiple IDs generated within the same millisecond by the same machine. <em>With 12 bits, up to 4,096 unique IDs can be generated per machine per millisecond.</em></p>
</li>
</ol>
<p>The format was created by Twitter (now X) and is used for the IDs of tweets. It is popularly believed that every snowflake has a unique structure, so they took the name "snowflake ID". The format has been adopted by other companies, including Discord and Instagram. The Mastodon social network uses a modified version.</p>
<p>The format was first announced by X/Twitter in June 2010. Due to implementation challenges, <a target="_blank" href="https://techcrunch.com/2010/10/12/twitter-snowflake/">they waited until later in the year to roll out the update</a>.</p>
<ul>
<li><p>X uses snowflake IDs for posts, direct messages, users, lists, and all other objects available over the API.</p>
</li>
<li><p>Discord also uses snowflakes, with their epoch set to the first second of the year 2015.</p>
</li>
<li><p>Instagram uses a modified version of the format, with 41 bits for a timestamp, and 10 bits for a sequence number.</p>
</li>
<li><p>Mastodon's modified format has 48 bits for a millisecond-level timestamp, as it uses the UNIX epoch. The remaining 16 bits are for sequence data.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/image-3.png" alt="image-3" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-problem-stated-by-twitter">"The Problem" stated by Twitter:</h3>
<blockquote>
<p>We currently use MySQL to store most of our online data. In the beginning, the data was in one small database instance which in turn became one large database instance and eventually many large database clusters. For various reasons, the details of which merit a whole blog post, we’re working to replace many of these systems with <a target="_blank" href="http://cassandra.apache.org/">the Cassandra distributed database</a> or horizontally sharded MySQL (using <a target="_blank" href="http://github.com/twitter/gizzard">gizzard</a>).</p>
<p>Unlike MySQL, Cassandra has no built-in way of generating unique ids – nor should it, since at the scale where Cassandra becomes interesting, it would be difficult to provide a one-size-fits-all solution for ids. Same goes for sharded MySQL. We needed something that could generate tens of thousands of ids per second in a highly available manner.</p>
<p>This naturally led us to choose an uncoordinated approach. These ids need to be <em>roughly sortable</em>, meaning that if tweets A and B are posted around the same time, they should have ids in close proximity to one another since this is how we and most Twitter clients sort tweets.</p>
<p>Additionally, these numbers have to fit into 64 bits. We’ve been through the painful process of growing the number of bits used to store tweet ids <a target="_blank" href="http://www.twitpocalypse.com/">before</a>. It’s unsurprisingly hard to do when you have over <a target="_blank" href="http://social.venturebeat.com/2010/04/14/twitter-applications/">100,000 different codebases involved</a>.</p>
</blockquote>
<p>Check out <a target="_blank" href="https://blog.x.com/engineering/en_us/a/2010/announcing-snowflake">here</a> for more information</p>
<h3 id="heading-finding-tweet-timestamps">Finding Tweet Timestamps</h3>
<p>We all know that deleting a tweet isn't truly possible—once it's out there, it's how Twitter is designed. However, Twitter's use of Snowflake IDs adds an interesting twist to this narrative. Snowflake IDs are designed to be unique and time-ordered, which makes them not just identifiers but also a trail that can be tracked.</p>
<p>On May 11, 2019, Derek Willis from Politwoops uncovered a <a target="_blank" href="https://gist.github.com/naumansiddiqui4/ba3398ea85ed0ef1f3af23d47b4dcd42">list of deleted tweet IDs</a>. By using the Snowflake structure, he was able to extract the timestamps from these IDs, and discovered the 107 missing tweets. This finding inspired the creation of TweetedAt, a tool designed to accurately retrieve timestamps from Snowflake IDs and estimate the timing of tweets generated before Snowflake was in use.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/image-2.png" alt="image-2" width="600" height="400" loading="lazy"></p>
<p>Check out <a target="_blank" href="https://ws-dl.blogspot.com/2019/08/2019-08-03-tweetedat-finding-tweet.html">here.</a></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Unique identifiers play a critical role in software engineering, ensuring data integrity and enabling efficient data management across distributed systems.</p>
<p>From traditional GUIDs to modern solutions like Snowflake IDs, each identifier system offers distinct advantages tailored to specific use cases.</p>
<p>As technology evolves, understanding these systems and their implementations becomes increasingly important for scaling applications effectively. By exploring the various versions and alternatives, we can make informed decisions that best suit our needs in managing data at scale.</p>
<h4 id="heading-cover-image-a-2017-post-celebrating-facebook-reaching-2-billion-usershttpswwwfacebookcomphotofbid10103832396388711ampseta941146602501">Cover image: <a target="_blank" href="https://www.facebook.com/photo/?fbid=10103832396388711&amp;set=a.941146602501">A 2017 post celebrating Facebook reaching 2 billion users</a>.</h4>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Best Practices for Scaling Your Node.js REST APIs ]]>
                </title>
                <description>
                    <![CDATA[ By Rishabh Rawat There is more to scalability than using cluster mode. In this tutorial, we'll explore 10 ways you can make your Node.js API ready to scale. When working on a project, we often get a few real nuggets here and there on how to do someth... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/nodejs-api-best-practices-for-scaling/</link>
                <guid isPermaLink="false">66d460c747a8245f78752ab5</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scaling ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 15 Sep 2022 16:59:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Node.js-Best-Practices-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Rishabh Rawat</p>
<p>There is more to scalability than using cluster mode. In this tutorial, we'll explore 10 ways you can make your Node.js API ready to scale.</p>
<p>When working on a project, we often get a few real nuggets here and there on how to do something in a better way. We get to learn retrospectively, and then we're fully prepared to apply it next time around. </p>
<p>But how often does that actually work out? I don't even remember what I did yesterday sometimes. So I wrote this article.</p>
<p>This is my attempt to document some of the best Node.js scalability practices that are not talked about as often.</p>
<p>You can adopt these practices at any stage in your Node.js project. It doesn't have to be a last-minute patch.</p>
<p>With that said, here's what we will cover in this article:</p>
<ol>
<li>🚦Use throttling</li>
<li>🐢 Optimize your database queries</li>
<li>䷪ Fail fast with circuit breaker</li>
<li>🔍 Log your checkpoints</li>
<li>🌠 Use Kafka over HTTP requests</li>
<li>🪝 Look out for memory leaks</li>
<li>🐇 Use caching</li>
<li>🎏 Use connection pooling</li>
<li>🕋 Seamless scale-ups</li>
<li>💎 OpenAPI compliant documentation</li>
</ol>
<h2 id="heading-use-throttling">Use Throttling</h2>
<p>Throttling allows you to limit access to your services to prevent them from being overwhelmed by too many requests. It has some clear benefits – you can safeguard your application whether it's a large burst of users or a <a target="_blank" href="https://en.wikipedia.org/wiki/Denial-of-service_attack">denial-of-service attack</a>.</p>
<p>The common place to implement a throttling mechanism is where the rate of input and output don't match. Particularly, when there is more inbound traffic than what a service can (or wants to) handle.</p>
<p>Let’s understand with a visualization.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/throttling-nodejs-best-practices-nodejs.drawio--5-.png" alt="throttling between services" width="600" height="400" loading="lazy">
<em>Your application is throttling requests from News Feed Service</em></p>
<p>There's throttling at the first junction point between your application and the News Feed Service:</p>
<ol>
<li><em>News Feed Service (NFS)</em> subscribes to your application for sending notifications.</li>
<li>It sends 1000 requests to your application every second.</li>
<li>Your application only handles 500 requests/sec based on the billing plan NFS subscribed to.</li>
<li>Notifications are sent for the first 500 requests.</li>
</ol>
<p>Now it is very important to note that all the requests by NFS that exceed the quota of 500 requests/sec should fail and have to be retried by the NFS.</p>
<p><strong>Why reject the extra requests when you can queue them?</strong> There are a couple of reasons:</p>
<ol>
<li>Accepting all the requests will cause your application to start accumulating them. It will become a single point of failure (by RAM/disk exhaustion) for all the clients subscribed to your application, including NFS.</li>
<li>You should not accept requests that are greater than the scope of the subscription plan of your clients (in this case, NFS).</li>
</ol>
<p>For application level rate limiting, you can use <a target="_blank" href="https://www.npmjs.com/package/express-rate-limit">express-rate-limit</a> middleware for your Express.js API. For network level throttling, you can find solutions like <a target="_blank" href="https://aws.amazon.com/waf/">WAF</a>.</p>
<p>If you are using a pub-sub mechanism, you can throttle your consumers or subscribers as well. For instance, you can choose to consume only limited bytes of data when consuming a Kafka topic by setting the <a target="_blank" href="https://kafka.js.org/docs/consuming#a-name-options-a-options">maxBytes option</a>.</p>
<h2 id="heading-optimize-your-database-queries">Optimize Your Database Queries</h2>
<p>There will be times when querying the database is the only choice. You might have not cached the data or it could be stale.</p>
<p>When that happens, make sure your database is prepared for it. Having enough RAM and disk IOPS is a good first step.</p>
<p>Secondly, optimize your queries as much as possible. For starters, here are a couple of things that will set you on the right path:</p>
<ol>
<li>Try to use indexed fields when querying. Don't over-index your tables in hopes of the best performance. <a target="_blank" href="https://www.mongodb.com/blog/post/performance-best-practices-indexing#:~:text=Eliminate%20Unnecessary%20Indexes">Indexes have their cost</a>.</li>
<li>For deletes, stick to soft deletes. If permanent deletion is necessary, delay it. (<a target="_blank" href="https://httpie.io/blog/stardust">interesting story</a>)</li>
<li>When reading data, only fetch the required fields using projection. If possible, strip away the unnecessary metadata and methods (for example, Mongoose has <a target="_blank" href="https://mongoosejs.com/docs/tutorials/lean.html">lean</a>).</li>
<li>Try to decouple database performance from the user experience. If CRUD on the database can happen in the background (that is, non-blocking), do it. Don't leave the user waiting.</li>
<li>Directly update the desired fields using update queries. Don't fetch the document, update the field, and save the whole document back to the database. It has network and database overhead.</li>
</ol>
<h2 id="heading-fail-fast-with-a-circuit-breaker">Fail Fast with a Circuit Breaker</h2>
<p>Imagine you get burst traffic on your Node.js application, and one of the external services required to fulfill the requests is down. Would you want to keep hitting the dead end for every request thereafter? Definitely Not. We don't want to waste time and resources on the requests destined to fail.</p>
<p>This is the whole idea of a circuit breaker. <strong>Fail early.</strong> <strong>Fail fast</strong>.</p>
<p>For example, if 50 out of 100 requests fail, it doesn't allow any more requests to that external service for the next X seconds. It prevents firing requests that are bound to fail.</p>
<p>Once the circuit resets, it allows requests to go through. If they fail again, the circuit breaks and the cycle repeats.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/circuit-breaker-nodejs-best-practices-for-scale.drawio--1-.png" alt="Node.js Opposum circuit breaker states" width="600" height="400" loading="lazy">
<em>Node.js Opposum circuit breaker states</em></p>
<p>To learn more about how to add a circuit breaker to your Node.js application, check out <a target="_blank" href="https://github.com/nodeshift/opossum">Opposum</a>. You can read more on circuit breakers <a target="_blank" href="https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern">here</a>.</p>
<h2 id="heading-log-your-checkpoints">Log Your Checkpoints</h2>
<p>A good logging setup allows you to spot errors quickly. You can create visualizations to understand your app's behavior, set up alerts, and debug efficiently.</p>
<p>You can check out the <a target="_blank" href="https://www.elastic.co/what-is/elk-stack">ELK stack</a> for setting up a good logging and alerting pipeline.</p>
<p>While logging is an essential tool, it is very easy to overdo it. If you start logging everything, you can end up exhausting your disk IOPS causing your application to suffer.</p>
<p><strong>As a good rule of thumb is to only log checkpoints.</strong></p>
<p>Checkpoints can be:</p>
<ol>
<li>Requests, as they enter the main control flow in your application and after they are validated and sanitized.</li>
<li>Request and response when interacting with an external service/SDK/API.</li>
<li>The final response to that request.</li>
<li>Helpful error messages for your catch handlers (with sane defaults for error messages).</li>
</ol>
<p><strong>PS:</strong> If a request goes through multiple services during the lifecycle, you can pass along a unique ID in the logs to capture a particular request across all the services.</p>
<h2 id="heading-use-kafka-over-http-requests">Use Kafka Over HTTP Requests</h2>
<p>While HTTP has its use-cases, it is easy to overdo it. Avoid using HTTP requests where it is not necessary.</p>
<p>Let's understand this with the help of an example.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/kafka-over-http-nodejs-best-practices-for-scale.drawio.png" alt="Overview of Kafka pub-sub using topics" width="600" height="400" loading="lazy">
<em>Overview of Kafka pub-sub using topics</em></p>
<p>Let's say you are building a product like Amazon and there are two services:</p>
<ol>
<li>Vendor service</li>
<li>Inventory service</li>
</ol>
<p>Whenever you receive new stock from the vendor service, you push the stock details to a <a target="_blank" href="https://kafka.apache.org/intro">Kafka</a> topic. The inventory service listens to that topic and updates the database acknowledging the fresh restock.</p>
<p>To note that, you push the new stock data into the pipeline and move on. It is consumed by the inventory service at its own pace. <strong>Kafka allows you to decouple services.</strong></p>
<p>Now, what happens if your inventory service goes down? It is not straightforward with HTTP requests. Whereas in the case of Kafka, you can replay the intended messages (for example using <a target="_blank" href="https://github.com/edenhill/kcat">kcat</a>). <strong>With Kafka, you do not lose data after consumption.</strong></p>
<p>When an item comes back in stock, you might want to send out notifications to the users who wishlisted it. To do that, your notification service can listen to the same topic as the inventory service. This way, <strong>a single message bus is consumed at various places without</strong> <strong>HTTP overhead</strong>.</p>
<p>The <a target="_blank" href="https://kafka.js.org/docs/getting-started">Getting Started page</a> of KafkaJS shares the exact snippet to get you started with a basic setup in your Node.js application. I’d highly recommend checking it out, as there's a lot to explore.</p>
<h2 id="heading-look-out-for-memory-leaks">Look Out for Memory Leaks</h2>
<p>If you don't write memory-safe code and don't <a target="_blank" href="https://nodejs.org/en/docs/guides/simple-profiling/">profile</a> your application often, you may end up with a crashed server.</p>
<p>You do not want your profiling results to look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Image-Pasted-at-2022-9-6-14-58.png" alt="setTimeout retaining 98% memory after execution is over" width="600" height="400" loading="lazy">
<em>setTimeout retaining 98% memory after execution is over</em></p>
<p>For starters, I would recommend the following:</p>
<ol>
<li>Run your Node.js API with the <code>--inspect</code> flag.</li>
<li>Open <code>chrome://inspect/#devices</code> in your Chrome browser.</li>
<li>Click inspect &gt; <code>Memory</code> tab &gt; <code>Allocation instrumentation on timeline</code>.</li>
<li>Perform some operations on your app. You can use apache bench on macOS to fire off multiple requests. Run <code>curl cheat.sh/ab</code> in your terminal to learn how to use it.</li>
<li>Stop the recording and analyze the memory retainers.</li>
</ol>
<p>If you find any large blocks of retained memory, try to minimize it. There are a lot of resources on this topic. Start by googling "how to prevent memory leaks in Node.js".</p>
<p>Profiling your Node.js application and looking for memory utilization patterns should be regular practice. Let's make "Profiling Driven Refactor" (PDR) a thing?</p>
<h2 id="heading-use-caching-to-prevent-excessive-database-lookup">Use Caching to Prevent Excessive Database Lookup</h2>
<p>The goal is to not hit the database for every request your application gets. Storing the results in cache decreases the load on your database and boosts performance.</p>
<p>There are two strategies when working with caching.</p>
<p><strong>Write through</strong> caching makes sure the data is inserted into the database and the cache when a write operation happens. This keeps the cache relevant and leads to better performance. Downsides? Expensive cache as you store infrequently used data to the cache as well.</p>
<p>Whereas in <strong>Lazy loading</strong>, the data is only written to the cache when it is first read. The first request serves the data from the database but the consequent requests use the cache. It has a smaller cost but increased response time for the first request.</p>
<p>To decide the TTL (or Time To Live) for the cached data, ask yourself:</p>
<ol>
<li>How often the underlying data changes?</li>
<li>What is the risk of returning outdated data to the end user?</li>
</ol>
<p>If it is okay, <strong>having more TTL will help you with a better performance</strong>.</p>
<p>Importantly, <strong>add a slight delta to your TTLs</strong>. If your application receives a large burst of traffic and all of your cached data expires at once, it can lead to unbearable load on the database, affecting user experience.</p>
<pre><code>final TTL = estimated value <span class="hljs-keyword">of</span> TTL + small random delta
</code></pre><p>There are a number of policies to perform <a target="_blank" href="https://redis.io/docs/manual/eviction/">cache eviction</a>. But leaving it on default settings is a valid and accepted approach.</p>
<h2 id="heading-use-connection-pooling">Use Connection Pooling</h2>
<p>Opening a standalone connection to the database is costly. It involves TCP handshake, SSL, authentication and authorization checks, and so on.</p>
<p>Instead, you can leverage connection pooling.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/conection-pooling-nodejs-best-practices-for-scale.drawio--1-.png" alt="Database connection pool" width="600" height="400" loading="lazy">
<em>Database connection pool</em></p>
<p>A connection pool holds multiple connections at any given time. Whenever you need it, the pool manager assigns any available/idle connection. You get to skip the cold start phase of a brand new connection.</p>
<p>Why not max out the number of connections in the pool, then? Because it highly depends on your hardware resources. If you ignore it, performance can take a massive toll.</p>
<p>The more the connections, the less RAM each connection has, and the slower the queries that leverage RAM (for example sort). The same principle applies to your disk and CPU. With every new connection, you are spreading your resources thin across the connections.</p>
<p>You can tweak the number of connections till it matches your needs. For starters, you can get an estimate on the size you need from <a target="_blank" href="https://www.cybertec-postgresql.com/en/tuning-max_connections-in-postgresql/">here</a>.</p>
<p>Read about the MongoDB connection pool <a target="_blank" href="https://www.mongodb.com/docs/manual/administration/connection-pool-overview/">here</a>. For PostgreSQL, you can use the <code>node-postgres</code> package. It has built-in support for <a target="_blank" href="https://node-postgres.com/features/pooling">connection pooling</a>. </p>
<h2 id="heading-seamless-scale-ups">Seamless Scale-ups</h2>
<p>When your application's user base is starting to grow and you have already hit the ceiling on vertical scaling, what do you do? You scale horizontally.</p>
<blockquote>
<p>Vertical scaling means increasing the resources of a node (CPU, memory, etc.) whereas horizontal scaling involves adding more nodes to balance out the load on each node.</p>
</blockquote>
<p>If you’re using AWS, you can leverage Automatic Scaling Groups (ASG) which horizontally scales the number of servers based on a predefined rule (for example when CPU utilization is more than 50%).</p>
<p>You can even pre-schedule the scale up and scale down using <a target="_blank" href="https://docs.aws.amazon.com/autoscaling/application/userguide/examples-scheduled-actions.html">scheduled actions</a> in case of predictable traffic patterns (for example during the World Cup finals for a streaming service).</p>
<p>Once you have your ASG in place, adding a load balancer in front will make sure the traffic is routed to all the instances based on a chosen strategy (like <a target="_blank" href="https://en.wikipedia.org/wiki/Round-robin_scheduling">round robin</a>, for example).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/alb-nodejs-best-practices-for-scale.drawio--2-.png" alt="Load balancing multiple targets based on predefined rules" width="600" height="400" loading="lazy">
<em>Load balancing multiple targets based on predefined rules</em></p>
<p><strong>PS:</strong> It is always a good idea to estimate the requests your single server can handle (CPU, memory, disk, and so on) and allocate at least 30% more.</p>
<h2 id="heading-openapi-compliant-documentation">OpenAPI Compliant Documentation</h2>
<p>It might not directly affect your ability to scale a Node.js application, but I had to include this in the list. If you've ever done an API integration, you know it.</p>
<p>It is crucial to know everything about the API before you take a single step forward. It makes it easy to integrate, iterate, and reason about the design. Not to mention the gains in the speed of development.</p>
<p>Make sure to <strong>create OpenAPI Specification (OAS) for your Node.js API</strong>.</p>
<p>It allows you to create API documentation in an industry-standard manner. It acts as a single source of truth. When defined properly, it makes interacting with the API much more productive.</p>
<p>I have created and published a sample API documentation <a target="_blank" href="https://app.swaggerhub.com/apis/Rishabh570/test-API/0.1">here</a>. You can even inspect any API using the <a target="_blank" href="https://swagger.io/tools/swagger-inspector/">swagger inspector</a>.</p>
<p>You can find all of your API documentations and create new ones from the <a target="_blank" href="https://app.swaggerhub.com/home">Swagger Hub dashboard</a>.</p>
<h2 id="heading-now-you-go-captain">Now you go, captain!</h2>
<p>We have looked at ten lesser-known best practices to prepare Node.js for scale and how you can take your first steps with each one of them.</p>
<p>Now it is your turn to go through the checklist and explore the ones you find lacking in your Node.js application.</p>
<p></p>

  <div data-style="clean">
    <ul></ul>
    <div data-element="fields" data-stacked="false" class="seva-fields formkit-fields">
      <div class="formkit-field"></div>
      
        <div class="formkit-spinner">
          <div></div>
          <div></div>
          <div></div>
        </div><span>Grab your checklist ✨</span>
      
    </div>
  </div>
  


<p>I hope you found this helpful and it gave you some pointers to move forward in your scalability endeavor. This is not an exhaustive list of all the best practices – I have just included the ones I found are not talked about as much based on my experience.</p>
<p>Feel free to reach out on <a target="_blank" href="https://twitter.com/Rishabh570">Twitter</a>. I'd love to hear your feedback and suggestions on other best practices that you are using.</p>
<p>Liked the article? <a target="_blank" href="https://rrawat.com/newsletter">Get the improvement pills on backend web development</a> 💌.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Horizontal vs. Vertical Scaling – How to Scale a Database ]]>
                </title>
                <description>
                    <![CDATA[ Data Scalability Data scalability refers to the ability of a database to manipulate changing demands by adding and removing data. In this way, the database grows at the same pace as the software.  Via scaling, the database can expand or contract the ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/horizontal-vs-vertical-scaling-in-database/</link>
                <guid isPermaLink="false">66c4c63e034a1005e6c59644</guid>
                
                    <category>
                        <![CDATA[ vertical ]]>
                    </category>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Horizontal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scaling ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sophia Iroegbu ]]>
                </dc:creator>
                <pubDate>Thu, 09 Jun 2022 15:26:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/06/Tech-Blog-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-data-scalability">Data Scalability</h2>
<p>Data scalability refers to the ability of a database to manipulate changing demands by adding and removing data. In this way, the database grows at the same pace as the software. </p>
<p>Via scaling, the database can expand or contract the capacity of the system's resources to support the application's frequently changing usage.</p>
<p><strong>There are two ways a database can be scaled:</strong></p>
<ul>
<li>Horizontal scaling (scale-out)</li>
<li>Vertical scaling (scale-up)</li>
</ul>
<p>In this article, we'll look at both methods of scaling and discuss the advantages and disadvantages of each to help you choose.</p>
<h2 id="heading-horizontal-scaling">Horizontal Scaling</h2>
<p>This scaling approach adds more database nodes to handle the increased workload. It decreases the load on the server rather than expanding the individual servers. </p>
<p>When you need more capacity, you can add more servers to the cluster. Another name for this scaling method is <strong>Scaling out</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/scaling-out.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-advantages-of-horizontal-scaling">Advantages of Horizontal Scaling:</h3>
<ul>
<li>It is easy to upgrade</li>
<li>It is simple to implement and costs less</li>
<li>It offers flexible, scalable tools</li>
<li>It has limitless scaling with unlimited addition of server instances</li>
<li>Upgrading a horizontally scaled database is easy – just add a node to the server</li>
</ul>
<h3 id="heading-disadvantages-of-horizontal-scaling">Disadvantages of Horizontal Scaling:</h3>
<ul>
<li>Any bugs in the code will become more complex to debug and understand</li>
<li>The licensing fee is expensive as you will have more nodes that are licensed</li>
<li>The cost of the data center will increase significantly because of the increased space, cooling, and power required</li>
</ul>
<h3 id="heading-when-to-use-horizontal-scaling">When to use horizontal scaling:</h3>
<p>If you are dealing with more than a thousand users, it is best to use this scaling system because when the servers receive multiple user requests, everything will scale well.</p>
<p>It will also not crash because there are multiple servers.</p>
<h2 id="heading-vertical-scaling">Vertical Scaling</h2>
<p>The vertical scaling approach increases the capacity of a single machine by increasing the resources in the same logical server. This involves adding resources like memory, storage, and processing power to existing software, enhancing its performance. </p>
<p>This is the traditional method of scaling a database. Another name for this approach is <strong>Scale-up</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/02vertical-scaling-software-scalability.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-advantages-of-vertical-scaling">Advantages of Vertical Scaling:</h3>
<ul>
<li>The cost of the data center for the space, cooling, and power will be smaller</li>
<li>It is a cost-efficient software</li>
<li>It is easy to use and implement – the administrator can easily manage and maintain the software</li>
<li>The resources for this approach are flexible</li>
</ul>
<h3 id="heading-disadvantages-of-vertical-scaling">Disadvantages of Vertical Scaling:</h3>
<ul>
<li>The cost may be low, but you will need to pay for a license each time you scale up</li>
<li>The hardware costs more because of high-end servers</li>
<li>There is a limit to the amount you can upgrade</li>
<li>You are restricted to a single database vendor, and migration is challenging, or you may need to start over</li>
</ul>
<h3 id="heading-when-to-use-vertical-scaling">When to use vertical scaling:</h3>
<p>The vertical scaling approach is for you if you need a system with unique data consistency.</p>
<p>If you don't want to worry about balancing the server's workload, vertical scaling is the best option.</p>
<h2 id="heading-differences-between-vertical-and-horizontal-scaling">Differences Between Vertical and Horizontal Scaling</h2>
<table>
<thead>
<tr>
<th>Vertical</th>
<th>Horizontal</th>
</tr>
</thead>
<tbody>
<tr>
<td>The license costs less</td>
<td>The license costs more</td>
</tr>
<tr>
<td>This method increases the power of the server with additional individual servers</td>
<td>This method increases the power of the server with the existing server</td>
</tr>
<tr>
<td>This data is present on one single node, and it is scaled through a multicore</td>
<td>This is based on partitioning each node that contains a single part of data</td>
</tr>
</tbody>
</table>

<h2 id="heading-which-scaling-method-is-best-for-your-app">Which scaling method is best for your app?</h2>
<p>When choosing how to scale your database, you must consider what's at stake when you scale up and out. </p>
<p>Now we'll take a look at some factors to consider so you can choose which scaling system is best for your app:</p>
<h3 id="heading-load-balancing">Load balancing</h3>
<p>The vertical scaling system is best for balancing loads because you have a single server (vertical scaling), and there is no need to balance your load. Horizontal scaling requires you to balance the workload evenly.</p>
<h3 id="heading-point-of-failure">Point of failure</h3>
<p>The horizontal scaling system has more than one server, so when one server crashes, the next one picks up the slack. This means that there is no <em>single point of failure</em> which makes the system resilient.</p>
<p>But in the vertical scaling system, there is only one server, so once the server crashes, everything goes offline.</p>
<h3 id="heading-speed">Speed</h3>
<p>In terms of speed, the vertical scaling system is faster because, since it runs on one server, the vertical scaling system has an <em>interprocess communication</em> – that is, the server communicates within itself and it's fast. </p>
<p>The horizontal scaling system has network calls between two or more servers. This is also known as <em>Remote Procedure Calls (RPC).</em> RPCs are slow, though.</p>
<h3 id="heading-data-consistency">Data consistency</h3>
<p>When dealing with servers, you'll need to make sure that the data stored in them is consistent when end users send a request. </p>
<p>The vertical scaling system is data consistent because all information is on a single server. But the horizontal scaling system is scaled out with multiple servers, so data consistency can be a huge issue.</p>
<h3 id="heading-hardware-limitations">Hardware limitations</h3>
<p>The horizontal scaling system scales well because the number of servers you throw at a request is linear to the number of users in the database or server. The vertical scaling system, on the other hand, has a limitation because everything runs on a single server.</p>
<p>When choosing a system to scale your database, make sure to make a pros and cons list of the information in this article. It will help you decide which to use.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>A cloud computing model's scalability is the ability to quickly and instantly increase or decrease an IT capacity. Knowing how the two types of scaling work is crucial as this plays a massive role in your database or server management.</p>
<p>Quick recap...</p>
<ul>
<li>A server's role is to enhance its capacity to handle the increased workload, called <strong>Vertical scaling.</strong></li>
<li>A system's job is to add new nodes to manage the distributed workload, termed <strong>Horizontal scaling.</strong></li>
<li>The horizontal scaling system scales well as the number of users increases.</li>
<li>The vertical scaling system is faster due to its ability to inter-process communication.</li>
</ul>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Scale a Distributed System ]]>
                </title>
                <description>
                    <![CDATA[ By Apoorv Tyagi Designing a distributed system that supports millions of users is a complex task, and one that requires continuous improvement and refinement.  Recently I read a book by Alex Xu called "System Design Interview – An Insider's Guide". T... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-scale-a-distributed-system/</link>
                <guid isPermaLink="false">66d45d9acc7f04d2549a371e</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ distributed systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scaling ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 13 Dec 2021 23:37:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/photo-1515378960530-7c0da6231fb1-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Apoorv Tyagi</p>
<p>Designing a distributed system that supports millions of users is a complex task, and one that requires continuous improvement and refinement. </p>
<p>Recently I read a book by Alex Xu called "<em>System Design Interview – An Insider's Guide</em>". This article, inspired by the first part of the book, shares some popular techniques used by many large tech companies to scale their architecture to support up to a million users.</p>
<p>This is not an exhaustive list, but if you're a newer developer who's just getting started, this can help you build a stronger foundation for your career.</p>
<h2 id="heading-use-a-load-balancer"><strong>Use a </strong>Load<strong> B</strong>alancer<em>**</em></h2>
<p>A load balancer is a device that evenly distributes network traffic across several web servers. In this architecture, the clients do not connect to the servers directly – instead they connect to the public IP of the load balancer. </p>
<p>Using a load balancer also protects your site in the event of web server failure – and this, in turn, improves availability. For example,</p>
<ul>
<li>If one server goes down, all the traffic can be routed to the second server. This prevents the overall system from going offline.</li>
<li>If in the future the traffic grows and these two servers are not enough to handle all the requests properly, then you just need to add more servers to your pool of web servers and the load balancer automatically starts distributing requests to them.</li>
</ul>
<h3 id="heading-load-balancing-algorithms">Load Balancing Algorithms</h3>
<p>Let's look at some of the algorithms which a load balancer can use to choose a web server from a pool for an incoming request:</p>
<ul>
<li><strong>Round Robin</strong> – You start from the first server in the pool, move down to the next server, and when you're done with the last server you loop back up to the first and start working down the pool again.</li>
<li><strong>Load-based server</strong> – You assign a server based on whichever server has the smallest load currently, thereby increasing throughput.</li>
<li><strong>IP Hashing</strong> – You assign a server by hashing the IP address of incoming requests and using the hash value to do the modulo operation with the number of servers available in the server pool.</li>
</ul>
<h2 id="heading-use-caching"><strong>Use </strong>Cach<strong>ing</strong></h2>
<p>A cache stores the result of the previous responses so that any subsequent requests for the same data can be served faster. So you can use caching to minimize the network latency of a system.</p>
<p>You can significantly improve the performance of an application by decreasing the network calls to the database. This is because repeated database calls are expensive and cost time. </p>
<p>For example, every time a new user loads a website's home page, one or more database calls are made to fetch the data. This increases the response time. Caching can alleviate this problem by storing the results you know will get called often and those whose results get modified infrequently.</p>
<p>Here are a few considerations to keep in mind before using a cache:</p>
<ul>
<li><strong>Set an expiration policy:</strong> You should always have an expiration policy on your cache. If you don't have one, the data will get stored in the cache permanently and it will become stale.</li>
<li><strong>Sync the cache and database:</strong> You should build a mechanism to keep the database and the cache in sync. If any data modifying operations occur in the databases and the same change doesn't reflect in the cache then it will introduce inconsistencies in your system. </li>
<li><strong>Set an eviction policy</strong>: You should have an algorithm that can decide which existing items will get removed once the cache is full and you get a request to add other items to the cache. Least-recently-used (LRU) is one of the most popular cache eviction policies used today.</li>
</ul>
<h2 id="heading-use-a-content-delivery-network-cdn"><strong>Use a </strong>Content<strong> D</strong>elivery<strong> N</strong>etwork (CDN)<em>**</em></h2>
<p>A CDN or a Content Delivery Network is a network of geographically distributed servers that help improve the delivery of static content from a performance perspective. CDN servers are generally used to cache content like images, CSS, and JavaScript files.</p>
<p>Here is how a CDN works:</p>
<ul>
<li>When a client sends a request, a CDN server to the client will deliver all the static content related to the request.</li>
<li>If the CDN server does not have the required file, it then sends a request to the original web server.</li>
<li>The CDN caches the file and returns it to the client.</li>
<li>Let's say now another client sends the same request, then the file is returned from the CDN.</li>
</ul>
<p>Here are a few considerations to keep in mind before using a CDN:</p>
<ul>
<li><strong>Cost</strong>: CDNs are generally run by third-party providers and they charge you for the data transfers in and out of the CDN. So caching infrequently used assets should not be stored in the CDN.</li>
<li><strong>Fallback Mechanism</strong>: If a CDN fails, you should be able to detect it and start sending requests for resources from the original web server. So you should build a mechanism for how your application copes with a CDN failure.</li>
</ul>
<h2 id="heading-set-up-a-message-queue"><strong>Set Up a </strong>Message<strong> Q</strong>ueue<em>**</em></h2>
<p>A message queue allows an asynchronous form of communication. It acts as a buffer for the messages to get stored on the queue until they are processed.</p>
<p>The architecture of a message queue includes an input service, called publishers, that creates messages, publishes them to a message queue, and sends an event. Another service called subscribers receives these events and performs actions defined by the messages.</p>
<p>Both publishers and subscribers are decoupled from each other and that's what makes the message queue a preferred architecture for building scalable applications.</p>
<h3 id="heading-message-queue-example">Message queue example</h3>
<p>Consider the following use case:</p>
<p>You are building an application for ticket booking. As soon as a user completes their booking, a message confirming their payment and ticket should be triggered. This task may take some time to complete and it should not make our system wait for processing the next request.</p>
<p>Here, we can push the message details along with other metadata like the user's phone number to the message queue. Another worker service picks up the jobs from the message queue and asynchronously performs the message creation and sending tasks.</p>
<p>The publishers and the subscribers can be scaled independently. When the size of the queue increases, you can add more consumers to reduce the processing time.</p>
<h2 id="heading-choose-your-database-wisely"><strong>Choose Your </strong>Database<strong> Wisely</strong></h2>
<p>According to <a target="_blank" href="https://en.wikipedia.org/wiki/Database">Wikipedia</a>:</p>
<blockquote>
<p>A database is an organized collection of data stored and accessed via a computer system. </p>
</blockquote>
<p>Databases are used for the persistent storage of data. We generally have two types of databases, relational and non-relational.</p>
<h3 id="heading-relational-database">➔ Relational Database</h3>
<p>A relational database has strict relationships between entries stored in the database and they are highly structured. This is to ensure data integrity. For example, adding a new field to the table when its schema doesn't allow for it will throw an error.</p>
<p>Another important feature of relational databases is ACID transactions.</p>
<h4 id="heading-acid-transactions">ACID transactions</h4>
<p>These are a set of features that describe any given transactions (a set of read or write operations) that a good relational database should support.</p>
<p><strong>Atomicity</strong> means that when a transaction that comprises more than one operation takes place, the database must guarantee that if one operation fails the entire transaction fails. Either it happens completely or doesn't happen at all.</p>
<p><strong>Consistency</strong> means that each transaction in a database does not violate the data integrity constraints whenever the database changes state and does not corrupt the data. In simple terms, consistency means for every "read" operation, you'll receive the most recent "write" operation results.</p>
<p><strong>Isolation</strong> means that you can run multiple concurrent transactions on a database, without leading to any kind of inconsistency. All these multiple transactions will occur independently of each other.</p>
<p><strong>Durability</strong> means that once the transaction has completed execution, the updated data remains stored in the database. It will be saved on a disk and will be persistent even if a system failure occurs.</p>
<h3 id="heading-non-relational-databases">➔ Non-Relational Databases</h3>
<p>A non-relational database has a less rigid structure and may or may not have strict relationships between the entries stored in the database. The data typically is stored as key-value pairs. For example:</p>
<pre><code>[
    { 
        <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Apoorv"</span>,
        <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Tyagi"</span>,
        <span class="hljs-attr">gender</span>: <span class="hljs-string">"M"</span>
    },
    { 
        <span class="hljs-attr">name</span>: <span class="hljs-string">"Judit"</span>,
        <span class="hljs-attr">rank</span>: <span class="hljs-string">"Polgar"</span>,
        <span class="hljs-attr">gender</span>: <span class="hljs-string">"F"</span>
    },
    {
      <span class="hljs-comment">//...</span>
    },
]
</code></pre><p>Similar to the ACID properties of relational databases, the non-relational database offers BASE properties:</p>
<p><strong>Basically Available (BA)</strong> which states that the system guarantees availability even in the presence of multiple failures. </p>
<p><strong>Soft State (S)</strong> means the state of the system may change over time, even without application interaction due to eventual consistency. In NoSQL, unlike RDBMS, it is believed that data consistency is the developer's responsibility and should not be handled by the database.</p>
<p><strong>Eventual Consistency (E)</strong> means that the system will become consistent "eventually". However, there's no guarantee of when this will happen.</p>
<h3 id="heading-nosql-vs-sql">NoSQL vs SQL</h3>
<p>Non-relational databases (also often referred to as NoSQL databases) might be a better choice if:</p>
<ul>
<li>Your application requires low latency. Since there are no complex JOIN queries.</li>
<li>You have a large amount of unstructured data, or you do not have any relation among your data.</li>
</ul>
<h2 id="heading-how-to-scale-a-database">How to Scale a Database</h2>
<p>Let's now look at the various ways you can scale your database:</p>
<h3 id="heading-vertical-vs-horizontal-database-scaling">Vertical vs horizontal database scaling</h3>
<p>In vertical scaling, you scale by adding more power (CPU, RAM) to a single server.</p>
<p>In horizontal scaling, you scale by simply adding more servers to your pool of servers.</p>
<p>For low-scale applications, vertical scaling is a great option because of its simplicity. But vertical scaling has a hard limit. It is practically not possible to add unlimited RAM, CPU, and memory to a single server. </p>
<p>Because of this, it is recommended that you go for horizontal scaling (also known as sharding) for large-scale applications.</p>
<h3 id="heading-database-replication">Database replication</h3>
<p>This is the process of copying data from your central database to one or more databases.</p>
<p>You do database replication using primary-replica (formerly known as master-slave) architecture. The primary database generally only supports write operations. All the data modifying operations like insert or update will be sent to the primary database.</p>
<p>On the other hand, the replica databases get copies of the data from the primary database and only support read operations. All the data querying operations like read, fetch will be served by replica databases.</p>
<p>Advantages of database replication:</p>
<ul>
<li><strong>Performance Improvements</strong>: Database replication improves performance significantly as all the writes and updates happen in the primary node and all the read operations are distributed to replica nodes, thereby allowing more queries to run in parallel.</li>
<li><strong>High Availability</strong>: Since we create replicas of data across different nodes available in different parts of the world, the application remains functional even if one database node goes offline as you can access data from other nodes. In case the failure occurs in the primary node, any one of the replica nodes will get promoted to a primary node and serve the write/update operations until the original primary node comes back online.</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>That's it. Thanks for stopping by. I hope you found this article interesting and informative!</p>
<p>My DMs are always open if you want to discuss further on any tech topic or if you've got any questions, suggestions, or feedback in general:</p>
<ul>
<li><a target="_blank" href="https://twitter.com/apoorv__tyagi">Twitter</a></li>
<li><a target="_blank" href="https://www.linkedin.com/in/apoorvtyagi/">LinkedIn</a></li>
<li><a target="_blank" href="https://github.com/apoorvtyagi">GitHub</a></li>
<li><a target="_blank" href="https://apoorvtyagi.tech/">Blog</a></li>
</ul>
<p>Happy learning! 💻 😄</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Scale a System With Process Splitting and Redis ]]>
                </title>
                <description>
                    <![CDATA[ By Pramono Winata Have you ever gotten into trouble trying to handle a single process that's really huge or heavy? If so, I can help you figure out how to better manage it. In this article I will be sharing how I'm currently managing a single message... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/scale-system-split-processes/</link>
                <guid isPermaLink="false">66d4609cc7632f8bfbf1e485</guid>
                
                    <category>
                        <![CDATA[ Redis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 20 Jul 2021 19:26:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/07/photo-1508624217470-5ef0f947d8be.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Pramono Winata</p>
<p>Have you ever gotten into trouble trying to handle a single process that's really huge or heavy? If so, I can help you figure out how to better manage it.</p>
<p>In this article I will be sharing how I'm currently managing a single message that is too big to be processed on a single process. I've split it into different chunks, which results in separate processes.</p>
<p>I won't go into much technical detail, but more of the architectural process.<br>I'll discuss some bits about caching usage and pubsub, but I will not go into details on the implementation. Instead, I'll focus on the pattern itself.</p>
<h2 id="heading-the-problem">The Problem</h2>
<p><img src="https://images.unsplash.com/photo-1489533119213-66a5cd877091?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDh8fHN0YXJ0fGVufDB8fHx8MTYyNjYzMDgzMQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Begin." width="2000" height="1333" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@dsmacinnes?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Danielle MacInnes / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>Perhaps the first question that comes to your mind is why we need to split a single process into several concurrent processes?</p>
<p>There might be several reasons to do this. In my case, though, I did it because the message was just too big.</p>
<p>To give you some idea about my situation, let me brief you a bit with this simple diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/sad.png" alt="Image" width="600" height="400" loading="lazy">
<em>I'm not a great diagram maker, but this should get the point across</em></p>
<p>To simplify it with words, imagine two separate services, service A and service B, with a pubsub service in the middle of it. </p>
<p>If you are not sure what a pubsub service is, just imagine it as a broker that helps the message from one service reach the other service.</p>
<p>Service A will then publish a message and through the pubsub, service B will then process it. After it has finished the process, it will do another process to mark that the message has been processed.</p>
<p>Simple enough right?</p>
<p>It's just that in some cases when the message is too big, it will not successfully publish the message because of the pubsub service's limitations. </p>
<p>Alright, this should give you an overview of the issues that I've encountered. So how did I fix this problem? In the next section, I will run you through my solution.</p>
<h2 id="heading-my-first-approach">My First Approach</h2>
<p><img src="https://images.unsplash.com/photo-1513348355499-5bdba1597a80?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDg2fHx0aGlua3xlbnwwfHx8fDE2MjY2MzA4OTY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Think" width="2000" height="1333" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@dose?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Dose Media / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>The first thing that came to my mind was increasing the size that the pubsub service can handle, which is doable with a single config change.</p>
<p>But life won't be too interesting if it's that easy right? What happens if the message just keeps getting bigger? Do we keep increasing the size of the pubsub?</p>
<p>Turns out that doing so can result in a lot of scalability issues. Not good for a long term solution.</p>
<p>Then I came up with another solution that I thought might solve it: I split that message into several messages and tried to process those parts separately.</p>
<p>Now, the system looked like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/asda.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>My updated system/process</em></p>
<p>As you can see from the diagram, the message gets split into several smaller messages. How it's split and which part of the message needs to be split might differ for each case and flow. </p>
<p>In my case, though, my message actually contains a list of items so I can split it by each item.</p>
<p>Let's say that I have 10 items. Previously, it would publish all 10 items in one message. But now after splitting the message up, it will turn that message into 10 messages.</p>
<p>This results in a single process becoming several processes all together. A single publish will turn into 10 publishes which in turn will turn that single process into 10 processes. </p>
<p>This might not look ideal when you look at it that way, but this is the best solution I came up with and it sure does work.</p>
<p>So is that all, only splitting it up?</p>
<p>Not really – remember that final part where it marks the process as finished?<br>If so, you might wonder why that part is missing from my new diagram. </p>
<p>Don't worry – it's not that I forgot about it. I intentionally left it out for the next part.</p>
<p>The thing is, when you split the message and break it into several processes, your system might not know if the whole process is actually finished. This is another major issue that we need to tackle, and thankfully I managed to find a solution for that, too.</p>
<h2 id="heading-how-to-handle-finishing-processes">How to Handle Finishing Processes</h2>
<p><img src="https://images.unsplash.com/photo-1516434233442-0c69c369b66d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHN3YXJtfGVufDB8fHx8MTYyNjYzMDk3Mg&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="A whale in the sky( Starling roost at Otmoor UK )" width="2000" height="1333" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@tumbao1949?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;James Wainscoat / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>So how exactly do I know if the process has finished, since those processes are happening concurrently?</p>
<p>The solution that I came up with is storing the number of processes that need to be done and decrementing it each time a process finishes. This way we will be able to know if the last process has finished.</p>
<p>It sure sounds simple enough, as long as we have a reliable place to store that data.<br>And actually there quite a lot of options for that. One of them is called <a target="_blank" href="https://redis.io/">Redis</a>, and I am using that to deal with my issue here. </p>
<p>If you are not familiar with Redis, it is a service that is generally used as a cache.</p>
<p>We will manage our Redis mechanism like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/saddd.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding Redis to mark our process</em></p>
<p>The process looks exactly the same as before, but with the addition of Redis in the middle. You need to make sure you have a valid initial count for this case.</p>
<p>In my case, since I'm publishing a list, I can easily put the length of my list as my initial counter. And for the counter, I can just decrease it by one each time a process has finished. Then I will be able to know if I have finished all my processes simply by referring to my Redis counter. If it has reached 0, it means that I can safely mark that all of my processes are done.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>To sum it all up, I split the message into several messages which will be processed all together in several processes. To manage the message processes, I use Redis caching.</p>
<p>The solution that I have described above will not be a silver bullet every time you have a problem processing a very big message. There are other ways like streaming your message, but that will be a story for another day.</p>
<p>Thanks for reading my article through to the end! I sincerely hope that you enjoyed and found my article interesting and, most importantly, that it was useful.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Maintain Scalability in Your Python Code ]]>
                </title>
                <description>
                    <![CDATA[ By Shifa Martin Any application that processes data can start to perform slowly or even start to corrupt or break. It is better if developers are able to program quickly and add more value to coding.  As developers, we should have tools to prototype ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-scalable-apps-in-python/</link>
                <guid isPermaLink="false">66d460f651f567b42d9f84ad</guid>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 20 Aug 2019 17:51:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/08/python-coding.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shifa Martin</p>
<p>Any application that processes data can start to perform slowly or even start to corrupt or break. It is better if developers are able to program quickly and add more value to coding. </p>
<p>As developers, we should have tools to prototype quickly. That’s why we should invest effort in making an app that is scalable. Broadly, building a substantial and scalable application is possible with the Python programming language.</p>
<p>Python is a high-level programming language that is also object-oriented. With its qualities such as built-in data structures, dynamic binding, and dynamic typing, we can use it to develop applications as rapidly as possible. </p>
<p>Python can also be used as a glued scripting language that integrates the existing components and helps us build scalable applications.</p>
<p>Python is one of the pioneers of programming languages that developers can use to do all the scaling work. </p>
<p>Here are some tips you can check out for developing scalable apps in Python.</p>
<h2 id="heading-learn-to-cleverly-use-collections">Learn to Cleverly Use ‘Collections’</h2>
<p>Python support rich and powerful data structures/containers for ‘collections’ such as <a target="_blank" href="https://docs.python.org/3.6/library/stdtypes.html#dict">dict</a>, <a target="_blank" href="https://docs.python.org/3.6/library/stdtypes.html#list">list</a>, <a target="_blank" href="https://docs.python.org/3.6/library/stdtypes.html#set">set</a>, and <a target="_blank" href="https://docs.python.org/3.6/library/stdtypes.html#tuple">tuple</a>. They are so valuable in building scalable apps. However, overusing them can impact code scalability. It's easy to spot when collections have been overused. </p>
<pre><code class="lang-python2"># notebooks.csv holds meta information on a collection of notebooks:
# heading, writer, year of pub, etc.


# load_from_file returns a list of dicts.


notebooks = load_from_file('notebooks.csv')


notebook_summaries = dict()
for notebook in notebooks:


   notebook_summaries[notebook["heading"]] = notebook["summary"]


for heading, summary in notebook_summaries.items():


   # Do something interesting with the summary.


   print(heading, summary)
</code></pre>
<p>From the above code, you can clearly see it creates table mapping titles after reading notebook data from the CSV file. If you see it from the memory-usage viewpoint, there is nothing wrong if notebooks.csv has hundreds of titles. </p>
<p>However, it is not right if it is related to the inventory of entire notebook stores with dozens of titles. You can have either one or two issues with your coding which also depends on what version you are using, Python 2 or Python 3.</p>
<p>This creates a bottleneck issue with the scalability of code memory. Creating a data structure called notebook_summaries is unnecessary here but it improves the readability. The “for” line helps you immediately know that a loop is running here through the summaries. </p>
<p>The new data structure contains the full summary of every notebook that is likely to consume more memory than all the other fields. Suppose if a notebook consumes N bytes of memory, then the complete block will consume at least 1.5 * N bytes. </p>
<p><strong>This will scale better in Python 3</strong></p>
<pre><code class="lang-python">notebooks = load_from_file(<span class="hljs-string">'notebooks.csv'</span>)


<span class="hljs-keyword">for</span> notebook <span class="hljs-keyword">in</span> notebooks.items():


   print(notebook[<span class="hljs-string">"title"</span>], notebook[<span class="hljs-string">"summary"</span>])
</code></pre>
<p>I recommend that you create variables that are well-named as it helps boost the maintainability of your Python code.</p>
<h2 id="heading-intelligent-iterating-of-python-codes">Intelligent Iterating of Python Codes</h2>
<p>While developing large-size applications with Python, scalability is not the only thing you should consider. You can face several other problems. For example, the iteration issue is the most common one. </p>
<p>Sometimes the for line in your coding iterates over notebook_summaries.items() and creates another copy of notebooks. This iteration of code can be responsible for low code performance in which Python code starts to hang before initiating the for loop.<br>This happens because the notebook_summaries.items() forms a very large list that consumes more memory. Also it is because the Python code executes the bytecode after the forloop. </p>
<p>It will start allocating more memory for this list. Again the iterating issue affects Python 2 as well as Python 3's items() and makes an extra copy of notebooks_summaries' contents. Developers can use iteritems instead of items in Python 2:</p>
<p><strong>In Python 2, use "iteritems" instead of "items"</strong></p>
<pre><code class="lang-python">notebooks = load_from_file(<span class="hljs-string">'notebooks.csv'</span>)


    <span class="hljs-keyword">for</span> notebook <span class="hljs-keyword">in</span> notebooks.iteritems():


      print(notebook[<span class="hljs-string">"title"</span>], notebook[<span class="hljs-string">"summary"</span>])
</code></pre>
<p>So, the point here is to notice the difference between using an iterator in all Python versions and creating a list. It is the developer’s responsibility to justify the right pattern according to the coding context.</p>
<h2 id="heading-using-generators-for-scalability-in-python-code">Using ‘Generators’ For Scalability in Python Code</h2>
<p>The generator function allows you to create iterators in a simpler manner.  Imagine you are working on building a software program as Grammarly that takes in text, analyze the sentences, and perform some kind of grammar analysis. Each line of sentence will be split by a period followed by one or more characters.</p>
<p><strong>See the coding</strong> </p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> re
text = <span class="hljs-string">'''Full body of text. It has many sentences.

Some have grammatical errors and some are correct.'''</span>

sentences = re.analyzed(<span class="hljs-string">r'\.\s+'</span>, text)

<span class="hljs-keyword">for</span> sentence <span class="hljs-keyword">in</span> sentences:

   print(sentence)
</code></pre>
<p><strong>Run the listing</strong></p>
<pre><code class="lang-python">This <span class="hljs-keyword">is</span> a body of text
It has many sentences

Some have grammatical errors <span class="hljs-keyword">and</span> some are correct.
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">weathermaker</span>(<span class="hljs-params">volatility, days</span>):</span>
    <span class="hljs-string">'''
    Yield a series of messages giving the day's weather and occasional commentary
    volatility ‑ a float between 0 and 1; the greater this number the greater
  the likelihood that the weather will change on each given day
    days ‑ number of days for which to generate weather
    '''</span>
    <span class="hljs-comment">#Always start as if yesterday were sunny</span>
    current_weather = <span class="hljs-string">'sunny'</span>
    <span class="hljs-comment">#First item is the probability that the weather will stay the same</span>
    <span class="hljs-comment">#Second item is the probability that the weather will change</span>
    <span class="hljs-comment">#The higher the volatility the greater the likelihood of change</span>
    weights = <span class="hljs-number">1.0</span>‑volatility, volatility    <span class="hljs-comment">#For fun track how many sunny days in a row there have been</span>
    sunny_run = <span class="hljs-number">1</span>
    <span class="hljs-comment">#How many rainy days in a row there have been</span>
    rainy_run = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> day <span class="hljs-keyword">in</span> range(days):
        <span class="hljs-comment">#Figure out the opposite of the current weather</span>
        other_weather = <span class="hljs-string">'rainy'</span> <span class="hljs-keyword">if</span> current_weather == <span class="hljs-string">'sunny'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'sunny'</span>
        <span class="hljs-comment">#Set up to choose the next day's weather. First set up the choices</span>
        choose_from = current_weather, other_weather        <span class="hljs-comment">#random.choices returns a list of random choices based on the weights</span>
        <span class="hljs-comment">#By default a list of 1 item, so we grab that first and only item with 0 current_weather = random.choices(choose_from, weights)0        yield 'today it is ' + current_weather</span>
        <span class="hljs-keyword">if</span> current_weather == <span class="hljs-string">'sunny'</span>:
            <span class="hljs-comment">#Check for runs of three or more sunny days</span>
            sunny_run += <span class="hljs-number">1</span>
            rainy_run = <span class="hljs-number">0</span>
            <span class="hljs-keyword">if</span> sunny_run &gt;= <span class="hljs-number">3</span>:
                <span class="hljs-keyword">yield</span> <span class="hljs-string">"Uh oh! We're getting thirsty!"</span>
        <span class="hljs-keyword">else</span>:
            <span class="hljs-comment">#Check for runs of three or more rainy days</span>
            rainy_run += <span class="hljs-number">1</span>
            sunny_run = <span class="hljs-number">0</span>
            <span class="hljs-keyword">if</span> rainy_run &gt;= <span class="hljs-number">3</span>:
                <span class="hljs-keyword">yield</span> <span class="hljs-string">"Rain, rain go away!"</span>
    <span class="hljs-keyword">return</span>

<span class="hljs-comment">#Create a generator object and print its series of messages</span>
<span class="hljs-keyword">for</span> msg <span class="hljs-keyword">in</span> weathermaker(<span class="hljs-number">0.2</span>, <span class="hljs-number">10</span>):
    print(msg)
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-python">$ python weathermaker.py
today it <span class="hljs-keyword">is</span> sunny
today it <span class="hljs-keyword">is</span> sunny
Uh oh! We<span class="hljs-string">'re getting thirsty!
today it is sunny
Uh oh! We'</span>re getting thirsty!
today it <span class="hljs-keyword">is</span> sunny
Uh oh! We<span class="hljs-string">'re getting thirsty!
today it is rainy
today it is sunny
today it is rainy
today it is rainy
today it is rainy
Rain, rain go away!
today it is rainy
Rain, rain go away!</span>
</code></pre>
<p>From the above code it’s clear that <a target="_blank" href="https://wiki.python.org/moin/Generators">Python generators</a> are a great way to quickly create iterators. They have many benefits, and they allocate memory for each sentence one at a time. They also make it easier for developers to modify the code without screwing up. </p>
<p>Another benefit generators provide is the <a target="_blank" href="https://pythonspot.com/encapsulation/">encapsulation</a> that provides new and useful ways for you to package and isolate the internal code dependencies. This is why you can use generators in for loops.</p>
<p><strong>You can add multiple yield statements in a generator</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">nums3</span>():</span>
   n = <span class="hljs-number">0</span>

   <span class="hljs-keyword">while</span> n &lt; <span class="hljs-number">6</span>:

  <span class="hljs-keyword">yield</span> n
       n += <span class="hljs-number">1</span>
   <span class="hljs-keyword">yield</span> <span class="hljs-number">63</span> <span class="hljs-comment"># Second yield</span>
<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums3():
   print(num
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-python"><span class="hljs-number">0</span>
<span class="hljs-number">1</span>
<span class="hljs-number">2</span>
<span class="hljs-number">3</span>
<span class="hljs-number">63</span>
</code></pre>
<p><strong>Explanation of the code above</strong></p>
<p>Here the second yield is completed after the whileloop exits. When the function reaches the implicit return at the end, the iteration stops.</p>
<h2 id="heading-final-words">Final Words</h2>
<p>So, if you don’t use generators in your python code yet, learn to do so. I know you will be glad you did it. They are the core part of Python coding and can be useful for your next application development on Python.</p>
<p>No doubt, Python is a very useful, diverse, and well-maintained language, and there is no bound to the features. However, I have shared the ideas which I use in my day to day coding process to make things simple. </p>
<p><strong>ValueCoders is an experienced <a target="_blank" href="https://www.valuecoders.com/">software development company</a>. In case you need the Python development services, feel free to <a target="_blank" href="https://www.valuecoders.com/contact">get in touch</a><em>.</em></strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Essentials of monorepo development ]]>
                </title>
                <description>
                    <![CDATA[ By Ovidiu Bute The word monorepo is a combination between “mono”, as in the Greek word mónos (in translation, alone) and an abbreviation of the word repository. A simple concept if taken verbatim: one lonely repository. The domain is software enginee... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/monorepo-essentials/</link>
                <guid isPermaLink="false">66d4608cc7632f8bfbf1e471</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ monorepo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 13 Jun 2019 18:51:48 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca20a740569d1a4ca522a.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ovidiu Bute</p>
<p>The word monorepo is a combination between “<em>mono</em>”, as in the Greek word <em>mónos</em> (in translation, <strong>alone</strong>) and an abbreviation of the word <strong>repository</strong>. A simple concept if taken verbatim: one lonely repository. The domain is software engineering so we’re referring to a home for source code, multimedia assets, binary files, and so on. But this definition is just the tip of the iceberg, since a monorepo in practice is so much more.</p>
<p>In this article I plan to distill the pros and cons of having every piece of code your company owns in the same repository. At the end you should have a good idea about why you should consider working like this, what challenges you’ll face, what problems it’ll solve, and how much you’ll need to invest in it.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*pCRpcpi3mLE2I-e4FOnp5w.png" alt="Image" width="2000" height="1059" loading="lazy">
<em>Relative interest in the term “monorepo” since 2004, source: Google Trends</em></p>
<p>The term itself, as visible in the chart above, looks to be as new as 2017. However it would be a mistake to think that previously nobody was storing all of their code in one place. In fact during my first job back in 2009, the company I worked at stored every project in a single SVN repository, one directory per project. Indeed you may well be able to trace this practice back even further. But how can we explain the recent explosive popularity, then?</p>
<p>The reality is that storing code in a single spot is not the main selling point. In the past years the major tech companies — Google, Facebook, or Dropbox have been showing off their way of working together within the same repository at massive scale. Organizations of tens of thousands of engineers collaborating within one repository is an awesome sight. And a difficult engineering problem. So difficult in fact that these companies invest a lot of money into tools and systems that allow developers to work productively. These systems in turn have solved problems that you may not even realize you had. This is what fascinates people during tech talks. This is what’s been driving searches since 2017.</p>
<ul>
<li>Front-end development at Google, Alex Eagle: <a target="_blank" href="https://medium.com/@Jakeherringbone/you-too-can-love-the-monorepo-d95d1d6fcebe">https://medium.com/@Jakeherringbone/you-too-can-love-the-monorepo-d95d1d6fcebe</a></li>
<li>Google monorepo presentation, Rachel Potvin: <a target="_blank" href="https://www.youtube.com/watch?v=W71BTkUbdqE">https://www.youtube.com/watch?v=W71BTkUbdqE</a></li>
<li>Scaling Mercurial to the size of Facebook’s codebase, Durham Goode: <a target="_blank" href="https://code.fb.com/core-data/scaling-mercurial-at-facebook/">https://code.fb.com/core-data/scaling-mercurial-at-facebook/</a></li>
</ul>
<p>I’ve identified a few core features that a Google or a Facebook vetted monorepo offers. This is surely not an exhaustive list, but it’s a great starting point. When discussing each of one of these points, I took into consideration what life looks like without them, and what exactly do they solve. Certainly in our field of work everything is a trade-off, nothing’s free. For every pro that I list someone will find use-cases that directly contradict me, butI’m OK with that.</p>
<h4 id="heading-all-your-code-regardless-of-language-is-located-in-one-repository">All your code, regardless of language, is located in one repository</h4>
<p>The first advantage of storing everything in once place may not be immediately obvious, but as a developer, simply being able to freely browse through everything is of great impact. It helps foster a sort of team spirit and is also a very valuable and cheap way to distribute information. Have you ever asked yourself what projects are in development at your company? Past and present? Curious what a certain team is up to? How have they solved a particular engineering problem? How are they writing unit-tests?</p>
<p>In direct opposition to the monorepo we have the <strong>multirepo</strong> structure. Each project or module gets its own separate space. In such a system developers can spend quite a bit of time getting answers to the questions I listed above. The distributed nature of the work means there’s no single source of information that you can subscribe to.</p>
<p>There are companies that have transitioned from a multi to a monorepo layout by following only this feature from my list. Such a structure should not be confused with the topic of this article though. I’d define it instead as a <strong>collocated multirepo.</strong> Yes, everything is in one place, but the rest of the features on this list are far more interesting.</p>
<h4 id="heading-youre-able-to-organize-dependencies-between-modules-in-a-controlled-and-explicit-way">You‘re able to organize dependencies between modules in a controlled and explicit way</h4>
<p>The traditional, battle tested way of handling dependencies is by publishing versions to a separate storage system from continuous integration systems, or even manually, from development machines. These are versioned (or tagged) to make it easier to search later on. Now in a multirepo setup, each project has a set of dependencies of external origins (third parties) or internal, as in, published from inside the same company.</p>
<p>In order for one team to depend on another one’s code, everything needs to pass through a dependency management storage system. Examples of this are npm, MavenCentral, or PyPi. I said earlier that you can easily build a collocated multirepo just by storing everything in one place. Such a system is <strong>indirectly observable.</strong> Let’s examine why that’s important.</p>
<p>As developers, our time is split very unequally between reading and writing code. Now imagine having to debug an issue that has its root cause inside of a dependency. We can rule out third parties here, since that’s a difficult problem as it is. No, this problem occurs in a package published by another team in your company. If your project depends on the latest version, you’re in luck! Just navigate to the respective directory and grab a cup of coffee.</p>
<blockquote>
<p>“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”</p>
</blockquote>
<p>― Robert C. Martin, <a target="_blank" href="https://www.goodreads.com/work/quotes/3779106">Clean Code: A Handbook of Agile Software Craftsmanship</a></p>
<p>More often though you might depend on an older version. So now what do you do? Do you try and use your VCS to read through the older code? Do you try and read the actual artifact instead of the original code? What if it’s minified, as is usually the case with JavaScript?</p>
<p>Contrast this with Google’s system, for example — since code dependencies are direct, as in, there are essentially no versions anywhere, one can say the system is <strong>directly observable</strong>. The code you’re looking at is pretty much your entire world. I say mostly because of course there are always going to be minor exceptions to this rule, such as external dependencies that would be prohibitive to host yourself. But that shouldn’t take anything away from this discussion.</p>
<hr>
<p>While we’re on the topic of dependency management we should touch upon the subject of restrictions. Imagine a project where you’re able to depend on any source file you need. Nothing is off limits, you can import anything. For those of you that started their careers at least 10 years ago, this sounds like business as usual for the time. This is an almost complete definition of a <strong>monolith</strong>.</p>
<p>The name implies grandeur, scale, but more importantly, singularity. Practically every source file inside of a monolith cannot live outside of it. There’s a fundamental reason for this is relevant to our discussion: you don’t have an explicit and audit-able way of managing dependencies inside of a monolith. Everything is up for grabs, and it feels free and cheap. So naturally, developers end up creating a complex graph of imports and includes.</p>
<p>Nowadays practically everyone is doing microservices, there can be little doubt about that. Given sufficient scale, a codebase becomes a beast, as everything is inexorably linked to each other. I’m sure many developers will provide counter-arguments that monoliths can be managed in a clean, reasonable way without falling into this trap. But exceptions simply reinforce the initial statement. Microservices solve this by defining clear boundaries and responsibilities, and a monorepo is a natural extension of this philosophy. Typically modules offer a set of public exports, or APIs, and other modules are only able to use those as part of their contracts.</p>
<h4 id="heading-software-modules-reuse-common-infrastructure">Software modules reuse common infrastructure</h4>
<p>This is a topic that’s very near and dear to my heart. I’ll define <em>infrastructure</em> in this context, that of a software codebase, as the essential tools necessary to ensure productivity and code quality.</p>
<p>One of the reasons why I think betting your company on multirepos is a mistake has to do with a set of basic requirements any software engineering project should meet:</p>
<ul>
<li>A build system to be able to reliably produce a deliverable artifact.</li>
<li>A way to run automated tests.</li>
<li>A way to statically analyze code for common mistakes, potential bugs, and enforce best practices.</li>
<li>A way to install and manage third party dependencies, i.e. software modules which are external to your company.</li>
</ul>
<p>If you have your code split in multiple repositories, <strong>you need to replicate this work everywhere</strong>. Don’t underestimate how much work this involves! All of the features listed above require at the very minimum a set of configuration files which need to be maintained in perpetuity. Having them copied across more than two places basically guarantees you will always generate technical debt.</p>
<p>I know that some companies go to extreme lengths to minimize the impact of this. They’ll have their configurations bundled as scaffolding (<em>a la</em> create-react-app or yeoman), and use them to setup new repositories. But as we’ve seen in the section before this one, there’s no way to enforce that everyone’s on the latest version of these boilerplate dependencies! The amount of time spent upgrading each repository individually increases linearly in large codebases. Given sufficient scale, practically all published versions of an internal package will be depended on at the same time!</p>
<p>There’s a quote I absolutely love that relates to this conundrum:</p>
<blockquote>
<p>At scale, statistics are not your friend. The more instances of anything you have, the higher the likelihood one or more of them will break. Probably at the same time.</p>
</blockquote>
<p>— <a target="_blank" href="https://thenewstack.io/distributed-systems-hard/">Anne Curie</a></p>
<p>If you think distributed systems just refers to web services, I would disagree. Your codebase is an interconnected, living system. Tens, hundreds, or thousands of engineers are racing to get their code into production each day, all the while struggling to keep the build green and the code quality up. If anything, to me this sounds even scarier than a set of microservices :)</p>
<h4 id="heading-changes-are-always-reflected-throughout-the-entire-repository">Changes are always reflected throughout the entire repository</h4>
<p>This is highly dependent on the rest of the features. It’s one of the benefits that’s easier to understand through example.</p>
<p>Let’s say I work at a company that builds web applications for customers all around the world. Everything is organized into modules, as is exemplified below via the popular open-source project <a target="_blank" href="https://github.com/babel/babel/">Babel</a>. At this company we all use ReactJS for front-end work, and out of pure coincidence, all of our projects are on the same version of it.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*SURhmpcSs3ZlS4AfRpBqSA.png" alt="Image" width="1960" height="1872" loading="lazy">
_Babel’s myriad of modules: [https://github.com/babel/babel/tree/master/packages](https://github.com/babel/babel/tree/master/packages" data-href="https://github.com/babel/babel/tree/master/packages" class="markup--anchor markup--figure-anchor" rel="nofollow noopener noopener" target="<em>blank)</em></p>
<p>But the folks at Facebook publish the latest version of React and we realize that upgrading to it is not trivial. To be more productive, we’ve built a library of reusable components that resides as a separate module. All projects depend on it. This new React version brings lots of breaking changes that affect it. What options do we have for doing the upgrade?</p>
<p>This is typically where monorepo adversaries would shoot down the entire concept. It’s easy to say that we’ve worked ourselves into a corner and that the multirepo structure would’ve been a superior choice given the circumstances. Indeed in the latter case what we would do is just gradually adopt the new React version in our projects one by one, preceded by a major version upgrade of our core components module.</p>
<p>But I would say this creates more problems than it solves. <strong>A core dependency breaking change release creates a schism in your engineering team</strong>. You now have two cores to maintain: the new one, which is used by a couple, brave teams in a few projects, and the older one, still depended on by almost the entire company.</p>
<p>Let’s take this problem to a bigger scale for further analysis. Our company may have some projects which are still in production, but are just in maintenance mode, and don’t have any active development teams assigned to them. These projects will probably be the last ones to migrate, extending the time window in which you keep working on two cores at the same time. The old version will still receive bugs or security fixes even though it’s deprecated, as you can’t risk your customers’ businesses.</p>
<p>All of this is to say that <strong>a multirepo solution promotes and enables a constant state of technical debt</strong>. There are lots of migrations going on, modules that depend on older versions of other modules, and many, many deprecation policies which may or may not be enforceable.</p>
<p>Let’s now consider an alternative solution to the React upgrade problem. By having all of the code in one place, and dependent on each other directly, without versioning, we’re left with one option: we have to do all of the work upfront, in all modules simultaneously.</p>
<p>If that sounds like a scary proposition, I don’t blame you. It’s terrifying to think about, at first. However the advantage is clear: no migrations, no technical debt, less confusion around the state of our codebase. In practical terms, there is one obstacle to overcome with this solution — there may be hundreds, thousands, or millions of lines of code that need to be changed all at once. By having separate projects we avoid the sheer volume of work by doing it piece by piece. It’s still the same total amount of changes, but we’re naturally inclined to think it would be easier to do that over time, rather than in one push.</p>
<p>To solve this last problem large companies have turned to <em>codemods</em> — programmatic transformations of source code that can run at very large scale. There are numerous tutorials out there if you’re interested, but the gist of it is — you write code that first detects certain patterns in your source code, and then applies specific changes to it. To take our React example further, you could write a codemod that replaces a deprecated API with a newer one, and even apply logic changes if necessary. Indeed this is how Facebook recommends you migrate from one version of their library to the next. It’s how they’re doing it internally. Check out their <a target="_blank" href="https://github.com/reactjs/react-codemod">open-source examples</a>.</p>
<p>Viewed from this angle, a migration doesn’t seem as scary as before. You do all of your research upfront, you define how you want to essentially rewrite the affected code, and apply the changes more or less all at once. This to me is a robust solution. I’ve seen it in action, it can be done. It’s indeed amazing when it works and lately more and more companies are adopting it.</p>
<h4 id="heading-drawbacks">Drawbacks</h4>
<p>The old adage of <em>“there’s no such thing as a free lunch”</em> certainly applies here, as well. I’ve talked about a lot of pros, but there are some cons which you need to think about.</p>
<p>Given that everyone is working in the same place, and everything is interconnected, <strong>tests</strong> become the blood of the whole system. Trying to make a change that impacts potentially thousands of lines of code (or more) without the safety net of automated tests is simply not possible.</p>
<p>Why is this any different from traditional ways of storing code? I’d say that versioned modules hide this particular problem, at the expense of creating technical debt. If you own a module that depends on another team’s code, by way of a strict version number, then you’re in charge of upgrading it. If you don’t have sufficient test coverage, you’ll err on the side of caution and simply <strong>delay upgrading</strong> until you’re confident the module doesn’t affect your own project. As we’ve discussed earlier, this has a serious long term consequences, but it’s a viable strategy nonetheless. Especially if your business doesn’t actually promote long term projects.</p>
<p>We mentioned the benefit of every contributor being able to access all of the source code in your organization. If we flip that around, this can also be a problem for some types of work. There’s no easy way you can restrict access to projects. This is important if you consider government or military contracts as they typically have strict security requirements.</p>
<p>Finally let’s consider continuous integration. You may be using a system such as Jenkins, Travis, or CircleCI, to manage the way your code is tested and delivered to customers. When you have more than one repository you typically set up one pipeline for each. Some teams even go further and have one dedicated CI instance per project. This is a flexible system that can adapt to the needs of each team. Your billing team may deploy to production once a week, while your web team would move faster and deploy multiple times a day.</p>
<p>If you’re considering moving to a monorepo, be wary of your CI system’s capabilities. It will have to do <strong>a lot of work</strong>. Simple tasks such as checking out the code, or building an artifact may become long running tasks which impact productivity. Google developed and runs its own custom CI solution, and for good reason. Nothing available on the market was good enough.</p>
<p>Now before you conclude that this is a blocker, I’d recommend you carefully analyse your project and the tools you use. If you’re using git, for example, there’s a myth going around that it can’t handle big repositories. This is demonstrably inaccurate, as best exemplified by the project that inspired git in the first place, the Linux Kernel.</p>
<p>Make your own research and see how many files and lines of code you have, and try to predict how much your project will grow. If you’re nowhere near the scale of the Kernel, then you’re OK. You could also make the point that git isn’t very good at storing binaries. <a target="_blank" href="https://git-lfs.github.com/">LFS</a> aims to solve that. You can also rewrite your history to delete old binaries in order to optimize performance.</p>
<p>In a similar vein, open-source CI systems are much more powerful than you think. Jenkins for example can scale to hundreds of jobs, dozens of workers, and can serve the needs of a large team with ease. Can it do Google scale? Absolutely not! But do you have <strong>tens of thousands</strong> of engineers pushing to production every day? The plateau at which these tools stop performing is so high, it’s not worth thinking about until you’re close to it. And chances are, you’ll know when you’re getting close.</p>
<p>And finally, there’s cost. You’ll need at least one dedicated team to pull this off. Because the amount of work is certainly not trivial, and it demands passion and focus. This team will need to, and I’m just summarizing here, build and maintain in perpetuity what is essentially a platform that stores code, assets, build artifacts, reusable development infrastructure for running tests or static analysis, and a CI system able to withstand large workloads and traffic. If this sounds scary, it’s because it is. But you’ll have no problems convincing developers to join such a team, it’s the type of experience that’s hard to accumulate by doing side-projects at home.</p>
<h4 id="heading-in-closing">In closing</h4>
<p>I’ve talked about the many advantages of working in a monorepo, the drawbacks, and touched upon the costs. This setup is not for everyone. I wouldn’t encourage you to try it out without first evaluating exactly what your problems and your business requirements look like. And of course, do go through all of the possible alternatives before deciding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to scale your Node.js server using clustering ]]>
                </title>
                <description>
                    <![CDATA[ By Michele Riva Scalability is a hot topic in tech, and every programming language or framework provides its own way of handling high loads of traffic. Today, we’re going to see an easy and straightforward example about Node.js clustering. This is a ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-scale-your-node-js-server-using-clustering-c8d43c656e8f/</link>
                <guid isPermaLink="false">66c3544bb1d4339762339fbd</guid>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 27 Nov 2018 16:59:21 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*2sGG4VhopW3NxKzJ2NsJLw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Michele Riva</p>
<p>Scalability is a hot topic in tech, and every programming language or framework provides its own way of handling high loads of traffic.</p>
<p>Today, we’re going to see an easy and straightforward example about Node.js clustering. This is a programming technique which will help you parallelize your code and speed up performance.</p>
<blockquote>
<p>“A single instance of Node.js runs in a single thread. To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load.”  </p>
<ul>
<li><a target="_blank" href="https://nodejs.org/api/cluster.html">Node.js Documentation</a></li>
</ul>
</blockquote>
<p>We’re gonna create a simple web server using <a target="_blank" href="https://koajs.com/">Koa</a>, which is really similar to <a target="_blank" href="https://expressjs.com">Express</a> in terms of use.</p>
<p>The complete example is available in <a target="_blank" href="https://github.com/micheleriva/node-server-clustering">this Github repository</a>.</p>
<h4 id="heading-what-were-gonna-build">What we’re gonna build</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*08Huxo1zfXGZt8gGa3C66A.png" alt="Image" width="342" height="472" loading="lazy"></p>
<p>We’ll build a simple web server which will act as follows:</p>
<ol>
<li>Our server will receive a <code>POST</code> request, we’ll pretend that user is sending us a picture.</li>
<li>We’ll copy an image from the filesystem into a temporary directory.</li>
<li>We’ll flip it vertically using Jimp, an image processing library for Node.js.</li>
<li>We’ll save it to the file system.</li>
<li>We’ll delete it and we’ll send a response to the user.</li>
</ol>
<p>Of course, this is not a real world application, but is pretty close to one. We just want to measure the benefits of using clustering.</p>
<h4 id="heading-setting-up-the-project">Setting up the project</h4>
<p>I’m gonna use <code>yarn</code> to install my dependencies and initialize my project:</p>
<p>Since Node.js is single threaded, if our web server crashes, it will remain down until some other process will restarts it. So we’re gonna install <a target="_blank" href="https://github.com/foreverjs/forever">forever</a>, a simple daemon which will restart our web server if it ever crashes.</p>
<p>We’ll also install <a target="_blank" href="https://github.com/oliver-moran/jimp">Jimp</a>, Koa and Koa Router.</p>
<h4 id="heading-getting-started-with-koa">Getting started with Koa</h4>
<p>This is the folder structure we need to create:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*bBt-QIrjkRFFvj9Iq5SO8Q.png" alt="Image" width="391" height="725" loading="lazy"></p>
<p>We’ll have an <code>src</code> folder which contains two JavaScript files: <code>cluster.js</code> and <code>standard.js</code> .</p>
<p>The first one will be the file where we’ll experiment with the <code>cluster</code> module. The second is a simple Koa server which will work without any clustering.</p>
<p>In the <code>module</code> directory, we’re gonna create two files: <code>job.js</code> and <code>log.js</code>.</p>
<p><code>job.js</code> will perform the image manipulation work. <code>log.js</code> will log every event that occurs during that process.</p>
<h4 id="heading-the-log-module">The Log module</h4>
<p>Log module will be a simple function which will take an argument and will write it to the <code>stdout</code> (similar to <code>console.log</code>).</p>
<p>It will also append the current timestamp at the beginning of the log. This will allow us to check when a process started and to measure its performance.</p>
<h4 id="heading-the-job-module">The Job module</h4>
<p>I’ll be honest, this is not a beautiful and super-optimized script. It’s just an easy job which will allow us to stress our machine.</p>
<h4 id="heading-the-koa-webserver">The Koa Webserver</h4>
<p>We’re gonna create a very simple webserver. It will respond on two routes with two different HTTP methods.</p>
<p>We’ll be able to perform a GET request on <code>[http://localhost:3000/](http://localhost:3000/.)</code>. Koa will respond with a simple text which will show us the current PID (process id).</p>
<p>The second route will only accept POST requests on the <code>/flip</code> path, and will perform the job that we just created.</p>
<p>We’ll also create a simple middleware which will set an <code>X-Response-Time</code> header. This will allow us to measure the performance.</p>
<p>Great! We can now start our server typing <code>node ./src/standard.js</code> and test our routes.</p>
<h4 id="heading-the-problem">The problem</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*r9s0KGLTNJLefEn9UzJIAA.jpeg" alt="Image" width="800" height="533" loading="lazy">
<em>The image I am currently manipulating (via Unsplash)</em></p>
<p>Let’s use my machine as a server:</p>
<ul>
<li>Macbook Pro 15-inch 2016</li>
<li>2.7GHz Intel Core i7</li>
<li>16GB RAM</li>
</ul>
<p>If I make a POST request, the script above will send me a response in ~3800 milliseconds. Not so bad, given that the image I am currently working on is about 6.7MB.</p>
<p>I can try making more requests, but the response time won’t decrease too much. This is because the requests will be performed sequentially.</p>
<p>So, what would happen if I tried to make 10, 100, 1000 concurrent requests?</p>
<p>I made a simple Elixir script which performs multiple concurrent HTTP requests:</p>
<p>I chose Elixir because it’s really easy to create parallel processes, but you can use whatever you prefer!</p>
<h4 id="heading-testing-ten-concurrent-requests-without-clustering">Testing ten concurrent requests — without clustering</h4>
<p>As you can see, we spawn 10 concurrent processes from our iex (an Elixir REPL).</p>
<p>The Node.js server will immediately copy our image and start to flip it.<br>The first response will be logged after 16 seconds and the last one after 40 seconds.</p>
<p>Such a dramatic performance decrease! With just 10 concurrent requests, we decreased the webserver performance by 950%!</p>
<h4 id="heading-introducing-clustering">Introducing clustering</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*j_NBlIkdKQ8J11tdW60FQw.jpeg" alt="Image" width="800" height="533" loading="lazy">
<em>All credits to Pexels</em></p>
<p>Remember what I mentioned at the beginning of the article?</p>
<blockquote>
<p>To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load.</p>
</blockquote>
<p>Depending on which server we’re gonna run our Koa application, we could have a different number of cores.</p>
<p>Every core will be responsible for handling the load individually. Basically, each HTTP request will be satisfied by a single core.</p>
<p>So for example — my machine, which has eight cores, will handle eight concurrent requests.</p>
<p>We can now count how many CPUs we have thanks to the <code>os</code> module:</p>
<p>The <code>cpus()</code> method will return an array of objects that describe our CPUs. We can bind its length to a constant which will be called <code>numWorkers</code>, ’cause that’s the number of workers that we’re gonna use.</p>
<p>We’re now ready to require the <code>cluster</code> module.</p>
<p>We now need a way of splitting our main process into <code>N</code> distinct processes.<br>We’ll call our main process <code>master</code> and the other processes <code>workers</code>.</p>
<p>Node.js <code>cluster</code> module offers a method called <code>isMaster</code>. It will return a boolean value that will tell us if the current process is directed by a worker or master:</p>
<p>Great. The golden rule here is that we don’t want to serve our Koa application under the master process.</p>
<p>We want to create a Koa application for each worker, so when a request comes in, the first free worker will take care of it.</p>
<p>The <code>cluster.fork()</code> method will fit our purpose:</p>
<p>Ok, at first that may be a little tricky.</p>
<p>As you can see in the script above, if our script has been executed by the master process, we’re gonna declare a constant called <code>workers</code>. This will create a worker for each core of our CPU, and will store all the information about them.</p>
<p>If you feel unsure about the adopted syntax, using <code>[…Array(x)].map()</code> is just the same as:</p>
<p>I just prefer to use immutable values while developing a high-concurrency app.</p>
<h4 id="heading-adding-koa">Adding Koa</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*xsU_-vw_YwvZnIzPX7375w.jpeg" alt="Image" width="800" height="533" loading="lazy">
<em>All credit to Pexels</em></p>
<p>As we said before, we don’t want to serve our Koa application under the master process.</p>
<p>Let’s copy our Koa app structure into the <code>else</code> statement, so we will be sure that it will be served by a worker:</p>
<p>As you can see, we also added a couple of event listeners in the <code>isMaster</code> statement:</p>
<p>The first one will tell us that a new worker has been spawned. The second one will create a new worker when one other worker crashes.</p>
<p>That way, the master process will only be responsible for creating new workers and orchestrating them. Every worker will serve an instance of Koa which will be accessible on the <code>:3000</code> port.</p>
<h4 id="heading-testing-ten-concurrent-requests-with-clustering">Testing ten concurrent requests — with clustering</h4>
<p>As you can see, we got our first response after about 10 seconds, and the last one after about 14 seconds. It’s an amazing improvement over the previous 40 second response time!</p>
<p>We made ten concurrent requests, and the Koa server took eight of them immediately. When the first worker has sent its response to the client, it took one of the remaining requests and processed it!</p>
<h4 id="heading-conclusion">Conclusion</h4>
<p>Node.js has an amazing capacity of handling high loads, but it wouldn’t be wise to stop a request until the server finishes its process.</p>
<p>In fact, Node.js webservers can handle thousands of concurrent requests only if you immediately send a response to the client.</p>
<p>A best practice would be to add a pub/sub messaging interface using Redis or any other amazing tool. When the client sends a request, the server starts a realtime communication with other services. This takes charge of expensive jobs.</p>
<p>Load balancers would also help a lot splitting out high traffic loads.</p>
<p>Once again, technology is giving us endless possibilities, and we’re sure to find the right solution to scale our application to infinity and beyond!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
