<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: darode</title>
    <description>The latest articles on DEV Community by darode (@darode).</description>
    <link>https://dev.to/darode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F325365%2F24e9b94b-01f1-485a-9d22-33c9ce34e00b.jpeg</url>
      <title>DEV Community: darode</title>
      <link>https://dev.to/darode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/darode"/>
    <language>en</language>
    <item>
      <title>The art of caching for backend applications</title>
      <dc:creator>darode</dc:creator>
      <pubDate>Wed, 18 Jan 2023 22:20:42 +0000</pubDate>
      <link>https://dev.to/darode/the-art-of-caching-for-backend-applications-3755</link>
      <guid>https://dev.to/darode/the-art-of-caching-for-backend-applications-3755</guid>
      <description>&lt;p&gt;Caching is a common technique we use when creating our applications to increase performance by storing frequently-used data in ephemeral but fast storage. A cache can help you to reduce the amount of time that an application takes to access that data, which can improve the overall user experience and make the application more responsive. &lt;/p&gt;

&lt;p&gt;When you have enough experience programming you start learning new things apart from the typical frameworks, libraries, design patterns, etc. One of these is how you can manage your information to improve your application performance, and here it’s where a cache comes in place.&lt;/p&gt;

&lt;p&gt;In this article, we will explore the basics of caching in software development and discuss some of the key considerations when implementing a cache for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is caching?
&lt;/h2&gt;

&lt;p&gt;First of all, we need to explain in depth a little bit more about caching.&lt;/p&gt;

&lt;p&gt;As we said, caching is a way to store data in a temporary location so that it can be accessed faster and more scalable by our application.&lt;/p&gt;

&lt;p&gt;This can be useful for reducing the amount of time that an application takes to retrieve data that is used frequently, such as the results of a database query or the contents of a frequently-visited web page. By storing this data in a cache, the application can access it faster the next time it is needed, which can improve the overall performance of the application dramatically.&lt;/p&gt;

&lt;p&gt;This is the main reason why it’s very important for a software developer to master all aspects of caching and use it to make faster and more reliable applications.&lt;/p&gt;

&lt;p&gt;This is the theory but, a lot should be said when you are going to implement a cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key features of a cache
&lt;/h2&gt;

&lt;p&gt;Before coding anything or installing the new trendy cache engine you need to think about the key aspects of a cache and make a lot of decisions.&lt;/p&gt;

&lt;p&gt;Depending on your use case, the resources you have, the programming language you are using and the way your application is going to use the data, you will choose a different kind of cache and a different configuration for it.&lt;/p&gt;

&lt;p&gt;The main parameters you should pay attention to are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;type of cache: you can choose to store data in a local or distributed cache&lt;/li&gt;
&lt;li&gt;data to store: you can choose between storing data as is or compiling it to save time for future usages in your app&lt;/li&gt;
&lt;li&gt;filling strategy: you can implement a lazy or eager cache depending on your use case the strategy chosen could improve or ruin your performance&lt;/li&gt;
&lt;li&gt;size of cache: you need to know the amount of data you are going to store because it will define the number of cache entries you can store&lt;/li&gt;
&lt;li&gt;keys: you should pay attention to the key or keys you use to store your data so it’s searchable the way you need it&lt;/li&gt;
&lt;li&gt;TTL (time to live): is another essential parameter that defines how long data will be stored in the cache&lt;/li&gt;
&lt;li&gt;eviction policy: this policy decides when a particular key will be removed from the cache to store new data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know... there are a lot of parameters to configure and a ton of decisions to be made even before you write a single line of code... that’s why a cache it’s so amazing!&lt;/p&gt;

&lt;p&gt;To make it easier we will review some of the most important in the following sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local or distributed cache
&lt;/h2&gt;

&lt;p&gt;Essentially we can identify two types of cache: local or distributed.&lt;/p&gt;

&lt;p&gt;A local cache works in the same machine that is going to use the information. In other words, a local cache uses the same machine resources as your application does. &lt;/p&gt;

&lt;p&gt;You can find two approaches to implementing a local cache: memory-based or disk-based&lt;/p&gt;

&lt;p&gt;A memory-based cache stores data in memory that could be inside your application memory or using another process, shared memory, etc. The main advantage of this implementation is that it is the fastest way to access data. On the other hand, it has a particular caveat and it’s that data is only available as long as the cache engine is running.&lt;/p&gt;

&lt;p&gt;A disk-based implementation uses disk storage which is slower than memory but can be persisted even if the application restarts. Another advantage is that usually, disk is cheaper and bigger than memory so you can store more data at lower costs.&lt;/p&gt;

&lt;p&gt;A distributed cache works across a network and multiple machines access it, it’s useful to scale applications and to share data between different servers supporting huge applications. The typical way to implement these caches is to install an instance or a cluster of a specific cache engine server. These systems are meant to scale horizontally so it’s very common for them to have some features like clustering and sharding out of the box.&lt;/p&gt;

&lt;p&gt;Which one is better? It depends on your use case... Because we have thousands of use cases for a cache, you have thousands of options to choose from. I have created the following comparison table to help you choose between a distributed or local cache for your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G0edoRoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abr66teebmthdpnkkc5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G0edoRoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abr66teebmthdpnkkc5y.png" alt="Image description" width="518" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see local and distributed caches are really different, but both make a lot of sense depending on your use case.&lt;/p&gt;

&lt;p&gt;Let’s say you have data, like for example, weather information for a particular city and you want to cache it. In this example data it’s the same for all requests, doesn’t change so often and it’s small (in size). This use case could use a small local cache in disk or memory so you will avoid scaling a remote cache if you have a lot of requests.&lt;/p&gt;

&lt;p&gt;Another use case that will need a distributed cache could be a requests access control system. These systems, for example, will store a cache with information about the number of requests per minute per API user. So you need to have all the information from all servers in a shared database to count all requests properly. In this use case, you need to use a distributed cache so you can share the information between all servers.&lt;/p&gt;

&lt;p&gt;Important to notice that here we are not speaking about a particular technology. It is because you can implement local or remote cache using the same technology in most cases. For example, you can use a Redis instance for a local or remote cache. Some of you could think it’s a lot of overengineering but makes a lot of sense if you want to change a local cache for a distributed one in the future. In this case, you will be able to use the same technology without changing a single line of code of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the best filling strategy
&lt;/h2&gt;

&lt;p&gt;When we talk about the filling strategy we are talking about the way data will be inserted into the cache. Here we have two ways to do it: eager or lazy.&lt;/p&gt;

&lt;p&gt;If you are going to use an eager approach it means you can handle a miss in your cache so you will insert or update data on a regular basis, but it doesn’t matter if some data is missing in your cache. The best way to implement this approach is using a background process that compiles data and loads the data in your cache.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xVdCjq_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttquaqxlfydruoaemujt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xVdCjq_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttquaqxlfydruoaemujt.png" alt="Image description" width="880" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lazy approach assumes that you cannot miss information in your cache so basically, your application should try to fetch data from your cache and if a miss occurs the app will go to a secondary data source (usually a relational database) to fetch the information and then insert it in the cache for future usages. To implement a lazy approach you need to create a logic to access your data in your application to handle missing data and use a fallback. Depending on your programming language or framework you will find different options to do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---qHCztq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otbdn34di16tdcwq3ixt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---qHCztq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otbdn34di16tdcwq3ixt.png" alt="Image description" width="880" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok but... what about a hybrid approach? Great question! For sure you can combine both strategies and, in most cases, it’s the best option if you want to get the most performance without missing any data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing your keys
&lt;/h2&gt;

&lt;p&gt;The most important aspect is that the keys should be searchable for your application so you need to pay attention and take your time to make the right decisions here.&lt;/p&gt;

&lt;p&gt;Keeping this in mind, you should adapt your keys to the way your application is going to retrieve data. So, if your application is going to retrieve data based on let’s say “product_id”, you should create a key using this information, for example, a key could have this format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;product-info:123&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If your application needs multiple parameters you can concatenate all necessary parameters to create your key. For example, you would want to store product information with translations per language, like product description, etc. In this case, a valid key could have the following format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;product-info:123:en&lt;br&gt;
product-info:123:es&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A common pitfall when choosing keys is storing huge amounts of data inside the same key. Because the cache systems are very fast indexing and managing information it doesn’t mean that they are not affected by network speed. So, if you are using a distributed cache you need to pay attention to the size of the data you store inside each key because it will be transferred through the network.&lt;/p&gt;

&lt;p&gt;To avoid this problem you can split your cache into several keys with specific information depending on how your application will use it. &lt;/p&gt;

&lt;p&gt;In the example we mentioned before, instead of storing all localized information in the same key you can split it in two. In one key you can store generic information like price, rating, packing size, etc. and use another key to store localized information like description, name, etc. &lt;/p&gt;

&lt;p&gt;This way you are going to have two keys, like this: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;product-info:123&lt;br&gt;
product-lang:123:es&lt;br&gt;
product-lang:123:en&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your application can use whatever is needed while retrieving the least data on each request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculating the best TTL value
&lt;/h2&gt;

&lt;p&gt;Another important parameter in your cache is TTL (time to live).&lt;/p&gt;

&lt;p&gt;As said before, TTL is like the expiration date of your data and defines when the value of a particular key could be deleted or replaced, so it’s no longer available for your application. Choosing the correct TTL is important to maximize your cache hit ratio without having deprecated data. &lt;/p&gt;

&lt;p&gt;A high TTL value will increase the hit ratio but could turn your cache into an unusable source of information because the data is not up to date. If the TTL value is low your hit ratio will be lower but the information will be refreshed very often.&lt;/p&gt;

&lt;p&gt;You can configure a static TTL value, the same for all keys, or a dynamic one, a different value depending on any key parameter. It’s very useful to define dynamic TTL values so you can improve the hit ratio keeping important keys up to date. For example, you can assign different TTL values for each type of product, language, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the correct eviction policy
&lt;/h2&gt;

&lt;p&gt;The last important parameter to configure your cache is the eviction policy. It decides which key will be deleted or replaced to store new information.&lt;/p&gt;

&lt;p&gt;The most common eviction policies are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;random: removes any key&lt;/li&gt;
&lt;li&gt;LRU (least recently used): removes the key that was not used recently&lt;/li&gt;
&lt;li&gt;LFU (least frequently used): removes the key that was not accessed very often&lt;/li&gt;
&lt;li&gt;TTL-based: removes keys nearly to expire&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each strategy has pros and cons but as a quick reference, you could use them as follows. &lt;/p&gt;

&lt;p&gt;You can use random eviction policy when you don’t expect a key to be used more than others, and it’s a good default strategy to start caching.&lt;/p&gt;

&lt;p&gt;If your cache has some keys that are accessed very often you should use LRU or LFU eviction policies so you want to ensure to preserve the most popular keys.&lt;/p&gt;

&lt;p&gt;If your cache uses different TTL values for each key a good option is to use a TTL-based eviction policy so you preserve keys with higher TTL which could be more important.&lt;/p&gt;

&lt;p&gt;Choosing an eviction policy sounds a little tricky but in reality, is a matter of trial and error. Usually changing the eviction policy doesn’t break the cache so you can try one and change to another one to see if it’s better for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the best technology for my cache?
&lt;/h2&gt;

&lt;p&gt;Finally, we should talk a little bit about specific technologies or engines you can use to implement your cache.&lt;/p&gt;

&lt;p&gt;First of all, let’s talk about local caches. You can use your hard drive to implement a cache. Yeah, I know... it’s not a proper engine but, for some use cases of local cache, caching information in a local file it’s more than enough and for sure it’s the easiest way to do it.&lt;/p&gt;

&lt;p&gt;The most used engines are in-memory databases, you can use them for local and remote caches. They are blazing fast and really easy to use because you don’t need to create indices and configure endless parameters. This kind of database could have some problems because some engines will clear all data if the process is restarted. Some examples of this technology are Redis and Memcached.&lt;/p&gt;

&lt;p&gt;Of course, you can use any database engine with more traditional capabilities (indices, expressive queries, etc.) NoSQL databases are very interesting to implement a cache because they support a really huge amount of requests per second. These kinds of databases have one advantage which is that they support data persistence when restarting the process and allow you to query your data (filtering, projections, etc.). In this group, you can find some databases like MongoDB, Elasticsearch or Cassandra.&lt;/p&gt;

&lt;p&gt;In case you decide to use a distributed cache, you need to check the horizontal scalability options the different technologies have and the additional costs. For example, if you deploy a cluster or HA architecture your setup will start with at least three instances, so the costs will at least triple if not quadruple.&lt;/p&gt;

&lt;p&gt;As you can see there is no one technology that is better than the other, but any of them could be a good one for your cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;As a brief summary, a cache is a way to store the most used data of your application to increase the performance of your application.&lt;/p&gt;

&lt;p&gt;The most important features of a cache are: &lt;br&gt;
type (local or distributed)&lt;br&gt;
the filling strategy&lt;br&gt;
how do you define the keys&lt;br&gt;
the TTL you choose to improve the hit ratio&lt;br&gt;
the eviction policy to delete data&lt;/p&gt;

&lt;p&gt;The most important thing is to ensure you have a proper hit ratio to increase your application performance as much as possible.&lt;/p&gt;

&lt;p&gt;You can use specific technology like Redis or Memcache which are in-memory databases specially designed to create the cache, or you can use other engines like NoSQL databases (MongoDB, Elasticsearch, etc.) which are designed to handle a high number of requests and allow you some advanced features like filtering, etc.&lt;/p&gt;

&lt;p&gt;Implementing a cache for an application it’s easier than it seems and it’s a wonderful experience when you see the increase in performance you get and how configurable these kinds of technologies are.&lt;/p&gt;

&lt;p&gt;Good luck and cache it all!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cache</category>
    </item>
    <item>
      <title>Scaling backend applications for dummies</title>
      <dc:creator>darode</dc:creator>
      <pubDate>Tue, 18 Oct 2022 22:21:06 +0000</pubDate>
      <link>https://dev.to/darode/scaling-backend-applications-for-dummies-5h6a</link>
      <guid>https://dev.to/darode/scaling-backend-applications-for-dummies-5h6a</guid>
      <description>&lt;p&gt;Maybe you, as every developer, have faced a situation when your application starts to slow down and shows poor performance.&lt;/p&gt;

&lt;p&gt;I know, it’s disappointing but it just happens. When you start working in an application and it gets more users and requests, some issues related to overloads, unexpected system failure and service downtime will occur. It’s completely ok, it just means you need to scale up your systems.&lt;/p&gt;

&lt;p&gt;If you have enough experience you may plan for some scenarios upfront based on previous projects and that’s a really good starting point because it means your architecture is, at least at some point, scalable.&lt;/p&gt;

&lt;p&gt;If you are new to this concept don’t worry, I have created a series of articles to introduce some concepts of scaling applications from the basics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scale... what?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before going further I think it's time to clarify some concepts.&lt;/p&gt;

&lt;p&gt;When we talk about scaling in software development we refer to the action to add more resources (hardware) to run a particular application.&lt;/p&gt;

&lt;p&gt;But if my program runs perfectly, why do I need to scale?&lt;/p&gt;

&lt;p&gt;Great question! Usually when you develop an application you do it in a certain context and when this context changes your application could be affected. &lt;/p&gt;

&lt;p&gt;Let me explain with an example. You are programming an ecommerce like Shopify. At the beginning you didn’t pay attention to database performance and it’s completely ok, the app has a few users and response times are quite good. Someday the performance drops and you realize that after the marketing campaign now your application has 100k users at the same time. Your application is the same but it doesn’t work as before, so what happened… exactly! the context your application runs on changed.&lt;/p&gt;

&lt;p&gt;These situations tend to happen from time to time. This is why it is so important to take care about the performance and the scalability of your application from the beginning.&lt;/p&gt;

&lt;p&gt;I’m not saying that you should create the next Google or Facebook with data centers around the world from day one, but you need a strategy and tools to scale your application. And that’s why this series of article exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can I scale my application?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we are on the same page so it's time to go deeper into scalability concepts.&lt;/p&gt;

&lt;p&gt;First of all I want to depict the typical flow when scaling an application.&lt;/p&gt;

&lt;p&gt;The first part of scaling an application is to know what it’s going on under the hood. In other words, we need to find what makes performance decrease in order to apply a solution to the problem.&lt;/p&gt;

&lt;p&gt;The second part is to apply a solution, obviously. At this point we are really lucky because there are a lot of solutions documented to help us when scaling our applications.&lt;/p&gt;

&lt;p&gt;If you ask me for a brief summary of this process should be something like this:&lt;/p&gt;

&lt;p&gt;Analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable observability tools&lt;/li&gt;
&lt;li&gt;Make a root cause analysis&lt;/li&gt;
&lt;li&gt;Improve:&lt;/li&gt;
&lt;li&gt;Optimize code and business logic&lt;/li&gt;
&lt;li&gt;Optimize database usage (e.g. slow queries)&lt;/li&gt;
&lt;li&gt;Use background processing&lt;/li&gt;
&lt;li&gt;Apply advanced scaling patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article and the following ones we will cover all these aspects and phases of the process. Let’s start talking about observability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable observability tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This sounds really obvious but it is not.&lt;/p&gt;

&lt;p&gt;Before applying any solution to your scaling problem you need to know where the problem is and what is causing it. We should apply different solutions depending on the problem. We are not going to apply the same improvements for slow queries in a database and for an overloaded server that cannot handle more requests.&lt;/p&gt;

&lt;p&gt;So first of all you need to audit your application. In the best case scenario your application has some observability tools in place like Kibana, Grafana, Prometheus or similar.  If so, you are lucky because you can check this data to spot the problem. If not, my advice is that you need to implement an observability tool right now. &lt;/p&gt;

&lt;p&gt;Because this article is an introduction to general concepts I’m not going to give you a deeper explanation on how to install and use any of these tools. You have hundreds of articles about it on the internet. But I want to give you some tips on what data you should gather to get a good observability of your application.&lt;/p&gt;

&lt;p&gt;The most important information you want to know about your application is:&lt;/p&gt;

&lt;p&gt;-application id: to identify your application in case you have many of them&lt;br&gt;
-request status: true/false or and error code, it’s up to you&lt;br&gt;
-request time: time elapsed from start to finish of request in seconds or milliseconds&lt;br&gt;
-server information: server name/cluster id or similar, helps you to spot specific problems&lt;br&gt;
-profiling information: information about time to run some methods or classes of your application, call to external apis, etc.&lt;/p&gt;

&lt;p&gt;You should gather this information for each request. If your app has a huge amount of requests consider gathering data for at least 10%-20% of requests. You can store this information as logs, but if you use an observability tool to display it you will be more productive because you get all your data at a glance.&lt;/p&gt;

&lt;p&gt;If you want to get your observability to the next level you can take a look at APM libraries. APM allows you to gather low level information like errors and stack traces from your app with a few lines of code using libraries. These libraries are available for most programming languages and frameworks and are compatible with all observability tools.&lt;/p&gt;

&lt;p&gt;In this section we should mention another source of information really useful to deal with performance problems and it’s the classic server monitoring. This information is usually available through specific server monitoring applications like Nagios, Centreon, Zabbix, Pandora FMS or more generic one like observability tools mentioned above. &lt;/p&gt;

&lt;p&gt;This information about usage of resources like CPU, RAM, network, etc. could give you a lot of information about your application performance and help you to analyze the problem. So don’t underestimate this kind of information when conducting a performance analysis of your application.&lt;/p&gt;

&lt;p&gt;With all the insights of what is happening inside our application we can spot performance problems and start making improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make root cause analysis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, you have all the information available and you need to start searching for the problems.&lt;/p&gt;

&lt;p&gt;I’m my experience the typical problems related to poor application performance are caused usually by:&lt;/p&gt;

&lt;p&gt;-requests to external APIs that take too long&lt;br&gt;
-not optimized database queries&lt;br&gt;
-non scalable code&lt;br&gt;
-lack of resources&lt;/p&gt;

&lt;p&gt;Problems with third party requests should be easy to spot because they tend to be consistent. Usually they are caused by a problem in the vendor’s systems and could be temporary or structural. Besides being easier to find, these problems are not so easy to fix, mainly because you cannot control the code of this API. So basically you should contact your vendor and see what they can do. If you are lucky enough and it’s an internal API developed by another team, just grab a coffee and talk with your colleague to see what is happening and how you can help.&lt;/p&gt;

&lt;p&gt;If your problem is related to non optimal queries then the approach is completely different. You should analyze your queries according to your database engine using some “explain” command and look for some improvements. We will cover this topic in the following sections.&lt;/p&gt;

&lt;p&gt;Another typical problem is a non optimal code, this is so general, I know… But in my experience a lot of problems are caused by code that is not optimized in terms of business logic and use of resources. Some examples are: repeated queries during the same request, doing business logic in requests that could be deferred, legacy code not useful but not refactored, and so on…&lt;/p&gt;

&lt;p&gt;A lack of resources problem is sometimes easy to spot if you have correct observability in place. Sometimes even if your code, queries, etc are optimized and perfect you can reach the limit of your database engine, web server, etc. In this case you will see errors with messages like “connection limit reached”. We will explore some options to solve them in the following sections.&lt;/p&gt;

&lt;p&gt;Using the observability information you should be able to identify problems and it’s kind easily. Once you do that the next step is to know how to start solving them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling by improving code performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First of all I want to talk about code performance because in my opinion it is the easiest problem to solve but the last one people address.&lt;/p&gt;

&lt;p&gt;Before optimizing database queries or making major refactors in your code, or improving your hardware you should review your implemented business logic.&lt;/p&gt;

&lt;p&gt;But… What should you look for? Great question! I can give you a list of example:&lt;/p&gt;

&lt;p&gt;repeated execution of code during same request, the result should be cached, don’t repeat again same thing&lt;br&gt;
legacy code no longer needed but that it's being executed, remove it immediately&lt;br&gt;
heavy weight loops or iterating same collection several times, try to loop collections as few as you can and avoid loops of loops when possible&lt;/p&gt;

&lt;p&gt;Those tips are the most common pitfalls but for sure there are plenty of bad practices to avoid. This is an introductory course so, this should be treated as an example to guide you on making a root cause analysis.&lt;/p&gt;

&lt;p&gt;If you improve these issues you can get more performance with a low effort and without making a huge refactor or even expending a lot of money to get more power for your servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling by improving database performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second place will go to query performance optimization.&lt;/p&gt;

&lt;p&gt;In my experience one of the most common issues when working with databases is just writing the structure or inserting information without paying attention to performance.&lt;/p&gt;

&lt;p&gt;For example, creating the correct index could make your application x10 times faster.&lt;/p&gt;

&lt;p&gt;So it’s crucial to ensure you have the correct indexes in place and that your queries and data structures are optimal to get the most of your database engine.&lt;/p&gt;

&lt;p&gt;I won’t dive deeper into database optimization because this is an introductory article. You have a lot of resources online for your database engine&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling by leveraging background processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When your code and database queries are optimized and you still have some part of your process that takes a long time you have the last silver bullet… You can try background processing.&lt;/p&gt;

&lt;p&gt;Some parts of business logic can slow down your application requests like logging, inserting a huge amount of data, etc. Sometimes these actions don’t belong to request’s business logic and you can defer them.&lt;/p&gt;

&lt;p&gt;A very good example is the “create user” request that sends the welcome email inside the same request. In this case the request just needs to insert user information into the database and return OK when done, you can send the email using a background process a few seconds later.&lt;/p&gt;

&lt;p&gt;But.. How can you do it? Ok, it’s easier than it seems.&lt;/p&gt;

&lt;p&gt;You can implement an event bus pattern using any message queue servers available like RabbitMQ, Kafka, AWS SQS, etc.&lt;/p&gt;

&lt;p&gt;The idea is to send an event informing about some action, for example “user created”, in the main request. Then you will have a separate process, usually a daemon, running in background listening to these events, for example “WelcomeEmailSenderListener” that sends the welcome email.&lt;/p&gt;

&lt;p&gt;Using background processing you can make your requests faster and it allows you to scale each part of your system separately allocating the resources they need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some advance scaling patterns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you implement all techniques above and your applications continue to perform really badly, then you need to apply some advanced scaling patterns. These patterns will help you out when gaining performances for your applications.&lt;/p&gt;

&lt;p&gt;Some of theses patterns are:&lt;/p&gt;

&lt;p&gt;-Implement some caching system&lt;br&gt;
-Scaling servers vertically &lt;br&gt;
-Scaling servers horizontally&lt;br&gt;
-Implement database sharding&lt;/p&gt;

&lt;p&gt;We will cover these patterns in the following articles in depth but to give you a brief introduction all of them are based on improving the usage of the hardware resources you have to run your application.&lt;/p&gt;

&lt;p&gt;In the real world we mix and match to get the best of all of them so you will end up with a more complex infrastructure and applications but on the other hand you will have a more reliable system that allows you to increase the number of requests and users effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scaling is very important to ensure your application can deal with a huge amount of requests and a lot of users which is a good sign that business is performing well.&lt;/p&gt;

&lt;p&gt;Enabling a good observability to gather performance data from your applications is key to understanding why your application has a low performance.&lt;/p&gt;

&lt;p&gt;It’s a good practice to check your code and database performance before adding more hardware to run your applications. Some easy to fix issues like removing legacy code, doing a refactor in business logic or creating some indexes in the database could improve your app performance ten times.&lt;/p&gt;

&lt;p&gt;You can improve your application performance by using more advanced scaling patterns like: caching, vertical and horizontal scaling, sharding, etc. that allow you to get the most of the hardware you use to run your application.&lt;/p&gt;

&lt;p&gt;This is the first article of a series that will cover some aspects of scaling applications, you will find more information about how to scale your application in the next articles.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
