2 Frontend System Design Concepts for Software Engineers

#99: A practical guide to building fast, scalable, and reliable web apps
2 Frontend System Design Concepts for Software Engineers

2 Frontend System Design Concepts for Software Engineers Get my system design playbook for FREE on newsletter signup:

Subscribe now


If you’re coming from the backend, you probably think the frontend is just “HTML, CSS, maybe some JavaScript.” But honestly? Modern frontend engineering has grown into something much closer to backend system design.

Just like your APIs need to be fast, scalable, and reliable, frontend apps also have to handle millions of users, load content quickly, and stay observable and secure.

This newsletter is a quick introduction to frontend system design.

We’ll take concepts you already know from the backend, like caching, deployment pipelines, observability, and security, and see how they apply in the browser.

By the end, you’ll see that the frontend isn’t just about buttons and forms. It’s about building systems that run right in the user’s browser.

Onward.


Supercharge AI Coding With Your Team’s Context (Sponsored)

Your AI tools are only as good as the context they have.Unblockedconnects your code, docs, and conversations so Cursor, Claude, and Copilot finally understand your system like your best engineer.

Start a free trial


I want to introduceShefali Jangidas a guest author.

](https://substackcdn.com/image/fetch/\(s_!JZ0g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e342437-67ac-47e3-b3f4-35fa0c59c43f_2222x742.png) ****Why it matters:**** * Just as fast as SSG, but the content stays fresh. * Perfect for dynamic websites like blogs or e-commerce sites. * Works with CDNs, so updates happen without downtime. ****Use case:**** E-commerce product pages where most content (e.g., descriptions or images) is static, but some parts, like prices or stock info, update occasionally. ISR keeps the page fresh without full redeploys, while real-time data, such as live prices, can come from APIs. ### ****3 Server-Side Rendering (SSR)**** Server-Side Rendering (SSR) works the other way around: the server builds the page for each request. It fetches the data, generates the HTML, and sends it to the user. Unlike Static Site Generation (SSG), which is great for mostly static pages, SSR is useful when content needs to stay fresh or personalised. For example, dashboards, user profiles, or live feeds. Because the system generates pages in real time, they always display the latest data instead of relying on pre-built files. Think of it like a regular API endpoint; everything gets computed on demand. [![](https://substackcdn.com/image/fetch/\)s_!d1KP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F460d29a1-f3d4-46d9-96f5-17d1570f0b17_2222x795.png)](https://substackcdn.com/image/fetch/\(s_!d1KP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F460d29a1-f3d4-46d9-96f5-17d1570f0b17_2222x795.png) ****Why it matters:**** * Keeps content fresh and easy to personalise. * Perfect for pages that need real-time data or personalised content. ****Note:****Under heavy traffic, SSR can slow down because it builds each page on demand, but caching can help balance load and speed. ****Use case:**** Social media feeds, admin dashboards, or user-specific pages where content varies by session. ### ****4 Client-Side Rendering (CSR)**** CSR means the browser does most of the work instead of the server. The server sends only a basic HTML page and some JavaScript. The browser then loads the data and builds the page on the fly. This approach is useful when you need rich interactivity, real-time updates, or pages that change often based on user actions - things that static or server-rendered pages can’t handle easily. Think of it like sending raw JSON and letting the client put it together. [![](https://substackcdn.com/image/fetch/\)s_!jV36!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecaf5033-0fa6-4209-b91e-0c6b2645e8b8_2222x764.png)](https://substackcdn.com/image/fetch/\(s_!jV36!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecaf5033-0fa6-4209-b91e-0c6b2645e8b8_2222x764.png) ****Note:****The first page load can be slower because the browser needs to download and run JavaScript before showing the content. Since pages get built in the browser, search engines might not see them immediately, so you might need extra setup like pre-rendering or server-side rendering for better SEO. ****Why it matters:**** * Reduces pressure on the server. * Makes the app more interactive and responsive. * Works best for apps people use for a long time, like dashboards or editors. ****Use case:**** Complex apps like Figma, Notion, or Google Docs, where the app is highly interactive and users stay on the page for extended sessions. ### ****5 Hybrid Rendering**** Sometimes, one approach just isn’t enough. Different parts of your app might have different needs. For example, some pages stay mostly the same, while others need fresh or personalised data. That’s where hybrid rendering comes in. It mixes different strategies: * Server-side rendering (SSR) for pages that need live or personalised content, * Static site generation (SSG) for pages that rarely change, * And client-side rendering (CSR) for sections with lots of interactivity. Think of it like combining pre-computed API responses with on-demand endpoints - all in the same system. [![](https://substackcdn.com/image/fetch/\)s_!gByI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e097d75-d6e9-438d-9d48-3592e0d277d7_2222x1231.png)](https://substackcdn.com/image/fetch/\(s_!gByI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e097d75-d6e9-438d-9d48-3592e0d277d7_2222x1231.png) ****Why it matters:**** * You get the best of everything: speed, fresh content, and interactivity. * Allows you to choose the right approach for each page or component. * Reduces overloading the server while keeping content dynamic where needed. ****Use case:**** Large-scale apps like e-commerce platforms often combine different rendering strategies: * The homepage and category pages use static generation for speed. * Product pages use incremental static regeneration to keep content fresh. * User account pages use server-side rendering for personalised data. * The shopping cart uses client-side rendering for real-time updates without page reloads. ### ****6 Content Delivery Networks (CDNs) & Edge Delivery**** No matter which rendering method you choose, serving content efficiently is super important. CDNs keep copies of your static files on servers worldwide. This lets users download them from a nearby location instead of your main server. This is especially useful for global audiences. For example, when someone in India visits a site hosted in the US, the CDN delivers the content from a local server, making it load much faster. Edge rendering takes this idea a step further. Instead of just serving static files, it can actually run code or build pages at the edge, closer to the user, which reduces latency even more. Think of it like having caches and compute nodes near your users, so requests go to a nearby server instead of your main database. [![](https://substackcdn.com/image/fetch/\)s_!zV8l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec91e87f-86de-43b0-a4fd-a7f6c96fcbf8_2222x825.png)](https://substackcdn.com/image/fetch/\(s_!zV8l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec91e87f-86de-43b0-a4fd-a7f6c96fcbf8_2222x825.png) ****Why it matters:**** * Faster load times everywhere. * Easy to scale to millions of users. * Works perfectly with SSG, ISR, SSR, or hybrid setups. ****Use case:**** Any globally distributed application. Media sites like The New York Times use CDNs to serve articles instantly worldwide. * * * ****Performance & Optimisation**** ---------------------------------- Now that you understand how your pages get rendered, the next obvious question is, “__How quickly do they actually load?__” Even the most beautiful app can be frustrating if it takes too long to open or lags while being used. In frontend system design, speed really matters. Let’s dive in! ### ****7 Web Performance Metrics**** To really understand your app’s speed, there are a few key metrics you should watch closely: * ****TTFB (Time to First Byte):****The time it takes for your browser to get the first piece of data back from the server or CDN after making a request. * ****FCP (First Contentful Paint):****The moment when something first appears on the screen, like text, an image, or a button, so the user knows the page is loading. * ****LCP (Largest Contentful Paint):****The time it takes for the main part of the page, like a large image or headline, to fully appear on the screen. * ****CLS (Cumulative Layout Shift):****It measures how much the page layout jumps around while loading, like when text or buttons suddenly shift because images or ads are still loading. These are basically the frontend versions of response time, throughput, and latency in backend systems. It’s important to keep a close eye on them; users can notice even minor delays of a few hundred milliseconds. [![](https://substackcdn.com/image/fetch/\)s_!g9z9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c33f370-32ca-4a57-b187-f71dbd7d6483_2222x1360.png)](https://substackcdn.com/image/fetch/\(s_!g9z9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c33f370-32ca-4a57-b187-f71dbd7d6483_2222x1360.png) ****Why it matters:**** * You can spot slow pages before users even notice. * Improves engagement and reduces bounce rates. * Helps guide your optimisations for a smoother experience. ****Use case:**** E-commerce sites must optimise for LCP (product images) and CLS (avoid layout shifts during checkout). News sites focus on FCP to show headlines quickly. ### ****8 Lazy Loading**** Of course, fast pages aren’t just about metrics; they’re also about smart resource management. Not everything on a page needs to load immediately. Lazy loading means loading heavy assets, like images, videos, or big components, only when they’re actually needed. This works by using techniques like the[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API "Intersection Observer API")or conditional imports, which tell the browser to fetch those resources only when they come into view or are triggered by user interaction. It’s like fetching extra data from an API only when the user asks for it. [![](https://substackcdn.com/image/fetch/\)s_!Z970!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d9b42f4-7fa4-4ab1-afa6-9481d99482bf_2222x825.png)](https://substackcdn.com/image/fetch/\(s_!Z970!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d9b42f4-7fa4-4ab1-afa6-9481d99482bf_2222x825.png) ****Why it matters:**** * Cuts down the initial load time. * Makes the pages feel faster and smoother. * Saves bandwidth for users who don’t need everything immediately. ****Use case:**** Image-heavy sites like Pinterest or Instagram use lazy loading extensively; images below the fold don’t load until you scroll. ### ****9 Service Workers & Caching**** Once you’ve optimised loading, you can make your app faster and more reliable using service workers and caching. Service workers are background scripts that run in a separate thread from your main web page. They can intercept network requests and cache important files or data, helping your app load faster and even work offline. Think of them as a smart middle layer between the browser and the network; if something is already cached, it’s served instantly instead of being fetched again. [![](https://substackcdn.com/image/fetch/\)s_!R0l9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e53e2bc-9448-4ec2-89f4-3299fd4d8cf0_2222x830.png)](https://substackcdn.com/image/fetch/\(s_!R0l9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e53e2bc-9448-4ec2-89f4-3299fd4d8cf0_2222x830.png) ****Why it matters:**** * Speeds up repeat visits. * Reduces the load on servers. * Keeps apps usable even with poor or no internet connection. ****Use case:**** Progressive Web Apps like Twitter Lite or Starbucks PWA, which cache core UI and recent content, so users can browse even on unstable mobile networks. * * * ****Data & State Management**** ------------------------------- Once your UI loads quickly, the next step is to think about the data behind it. In real apps, this data (also called state) can come from different places: * Some live inside a single component(a reusable piece of the UI, like a button), * Some are shared across the app, * And others come from APIs. How you manage this state can make or break your app’s speed, reliability, and scalability. ### ****10 State Management (Local, Global, Server Cache)**** * ****Local state:****data that lives inside a single component, used for things like toggles, forms, or small interactions. It’s simple to manage and doesn’t add much complexity. * ****Global state:****data that’s shared across multiple components or pages, like user info or theme settings. Tools like[Redux](https://redux.js.org/ "Redux"),[Zustand](https://zustand-demo.pmnd.rs/ "Zustand"), or[React Context](https://react.dev/learn/passing-data-deeply-with-context "React Context")help manage it. * ****Server cache:****stores frequently used API data on the client so the app doesn’t have to fetch it again and again, making it faster and reducing server load. Think of it like database caching: by deciding where data should live, you can make your app more responsive, reliable, and easier to scale. [![](https://substackcdn.com/image/fetch/\)s_!59Zh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd02164e2-f4a5-4c68-9438-e1157cbbdef5_2222x866.png)](https://substackcdn.com/image/fetch/\(s_!59Zh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd02164e2-f4a5-4c68-9438-e1157cbbdef5_2222x866.png) ****Why it matters:**** * Keeps your app responsive. * Reduces unnecessary API calls. * Makes scaling smoother as your app grows. ****Use case:**** Local state for a modal’s open/closed status. Global state for theme preference (dark mode) that affects every component. Server-side cache for user profile data displayed by multiple components. ### ****11 API Caching with Expiration**** Caching doesn’t stop at the component level. You can store API responses in memory,[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API "IndexedDB")(a browser database for larger data)__,__or[localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage "localStorage")(for smaller key-value data)__,__and set expiration rules to make sure data stays fresh. It’s like having a Redis cache server, but right in the browser instead of on your server. [![](https://substackcdn.com/image/fetch/\)s_!Gx9K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71ad33ac-a04f-4c06-8b8d-78d9e2912675_2222x866.png)](https://substackcdn.com/image/fetch/\(s_!Gx9K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71ad33ac-a04f-4c06-8b8d-78d9e2912675_2222x866.png) ****Why it matters:**** * Keeps data up-to-date for users. * Reduces repeated server requests. * Makes your app feel faster. ****Use case:**** A news app might cache articles for a few minutes so users can read offline, while comments refresh more often to stay up to date. Similarly, a SaaS dashboard could cache chart data while the user is on the page, then refresh it when they come back later. ### ****12 GraphQL vs REST (Reducing Over/Under-Fetching)**** How you fetch data also affects performance. * ****REST:****Can sometimes send too much data or not enough, making your app fetch extra information or require additional requests. * ****GraphQL:****A query language for APIs that lets the client ask for exactly the data it needs, avoiding extra or missing information. This avoids over-fetching or under-fetching data and helps reduce unnecessary requests. It’s like how you optimise database queries on the backend to make them faster and use less bandwidth, but this happens on the frontend. GraphQL sits between the client and the server as one endpoint. The client asks for exactly the data it needs, and the server’s GraphQL layer collects that data from databases or other APIs, then sends back a clean, organised response. This way, you make one flexible request instead of several REST calls, making it faster and more data-efficient. [![](https://substackcdn.com/image/fetch/\)s_!7DjY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38830cad-cd8e-4637-8e70-99bc0b4b3ca3_2222x866.png)](

Write a comment
No comments yet.