Web application too slow? Here are some easy ways to speed things up.
Tags: webdev, programming, performance, architecture
Published: 2023-05-17 11:04:25

Is your web application not fast enough? Or does it slow down when many requests are coming in? Here are some easy ways to fix it.

##Browser/HTTP caching
Web browsers are capable of temporary storing (caching) data that has been retrieved from a server before. You can use browser caching for images, CSS, JavaScript and other files, but also for dynamic responses from API endpoints. Browser caching can be implemented by HTTP headers like [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag), [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control), [Last modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) and more. Web Application frameworks have features to make implementing these headers easier.  

With a technique called cache busting you can make sure your users see the latest version when you deploy a new version of your web application. 
  
Be careful with sensitive data. When a user logs out and another user logs in the second user could access the data of the first user if not configured correctly.  

## CDN (Content Delivery Network)
A CDN can increase the performance and scalability of your server a lot. A CDN fetches static assets like HTML, CSS and images from your website and stores them on CDN servers. In your application you point to the CDN URL instead of your own URL. Web browsers will make requests to the CDN so this reduces the load on your server a lot. There are many CDN providers to choose from like [Microsoft Azure](https://azure.microsoft.com/en-us/products/cdn/) and [Cloudflare](https://www.cloudflare.com/). 

Be careful with sensitive data. You don't want that on an external server.
  
##Memory object caching
Caching objects in memory on the webserver is also an option. For example, let's say a user calls an endpoint which does the following:  
- Checks if data is available in the cache. If not:
  - Gets some data from the database  
  - Makes some heavy calculations  
  - Uses memory object caching to store the results for five minutes  
- Returns data to user  
Because the data is being cached the data only have to be fetched from the database once in 5 minutes. Same goes for the heavy calculations. Only one user per 5 minutes have to wait for all this and it reduces the resources needed on the web server and database server. This off course comes at the cost of more RAM usage. Here is a simple example on how to implement this in .NET Core:  
  
```  
[Route("api/[controller]")]  
[ApiController]  
public class ValuesController : ControllerBase  
{  
	private const string MY_CACHE_KEY = "my-key";  
	private readonly IMemoryCache _memoryCache;  
	public ValuesController(IMemoryCache memoryCache)  
	{  
		_memoryCache = memoryCache;  
	}  
  
	// GET: api/<ValuesController>  
	[HttpGet]  
	public IEnumerable<string> Get()  
	{  
		return _memoryCache.GetOrCreate(MY_CACHE_KEY, cacheEntry =>  
		{  
			cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);  
			return GetValuesFromDatabaseAndPerformCalculations();  
		});  
	}  
}  
```  
  
If you want to cache personal data of users, include a user identifier in the key so users cannot access each others data.  
  
##Horizontal scaling
Horizontal scaling is about adding extra servers on which a application runs. A load balancer distributes the requests evenly among the servers.  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7dwasu4fw7d8370qg5a.png)
  
Cloud platforms like [Microsoft Azure](https://azure.microsoft.com/en-us) and [AWS](https://aws.amazon.com/) or technologies like [Docker](https://www.docker.com/) or [Kubernetes](https://kubernetes.io/) provide features to make horizontal scaling easier. However, there are some downsides to this solution.  

- If the application keeps a state like data/variables in memory or data on the hard drive for example, you need to implement sticky sessions so the user will be directed to the right server.  
- You might want to dynamically add servers at a specific time or when the load on the application gets too high. Sticky sessions aren't an option anymore. The load balancer can't direct a user to the newly added webserver, because of the sticky session. If a server gets removed the state stored on that server is also removed. Dynamically adding and removing server requires an application to be completely stateless.  
- An extra server is more expensive.  
  
**Distributed caching**  
Memory object caching makes an application stateful because data is being stored in memory. If you have two servers which have different versions off data cached, users will see inconsistent responses. Distributed caching is the same as Memory object caching except that the data is stored on an external server. This comes at a cost of extra complexity and money. With technologies like Redis, Memcached and others it's possible to horizontally scale the caching nodes if one node isn't enough. Distributed caching can also be a great option if memory cache is taking too much RAM from your webserver. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2o5rjsr1k7he9fqex4y.png)