Frontend System Design: Non-Functional Requirements for Feeds (Performance)
June 2, 2026
In frontend system design interviews, feeds are one of the most common topics. Feeds are a core part of almost every social product, from Facebook and Twitter to Substack, which originally started as a newsletter platform but now also has feed-like experiences.
From a frontend perspective, a feed may not look especially hard to design. Many beginner frontend courses even use a simplified Twitter clone as a practice project.
But when a feature looks simple on the surface, the real difference between a basic design and a senior-level design often comes down to non-functional requirements. This article focuses on the most important frontend concerns for feeds: performance and scalability. We will split the discussion into two articles. This one focuses on performance.
Performance
For feeds, performance is arguably the most important non-functional requirement. For example, after Twitter was acquired and renamed X, there has been much more discussion about product stability and loading experience. You can find many complaints about X’s loading performance. If users have to wait four or five seconds before seeing any posts, they can still become frustrated and leave even if the feature technically works.
In backend system design, there is a lot of discussion about how to deliver posts to the frontend faster. But frontend architecture also has many opportunities to improve performance. Let’s walk through them one by one.
Choosing a rendering strategy
Before users can see a page, the frontend needs to render content. In a previous article, we discussed different frontend rendering strategies. If you are unfamiliar with that topic, it is worth reviewing first. For a feature like a feed, should we use CSR or SSR?
Around 2020, Meta shared in “Rebuilding our tech stack for the new Facebook.com” that they rebuilt the original PHP-based SSR application, which dated back to 2004, into a React-based CSR application. During that migration, the biggest challenge was startup performance: how quickly users could see content after opening the page. CSR first downloads JavaScript to the browser and only renders after that JavaScript runs.
Modern frontend applications, including Meta’s products, bundle frontend code. If the bundle is larger, the browser needs more time to download it. To reduce this cost, Meta used code splitting to divide the output into three bundles. The first bundle contained only a very small amount of skeleton UI so the page could render a basic frame. The second bundle contained the actual feed content. The third bundle contained elements that would not appear immediately, such as menu components that only show after a click.
Later, however, the industry, including React from Meta, gradually started re-exploring SSR. The motivation was to let users receive the HTML needed for initial content faster. As a result, most web feeds today are moving toward a hybrid model: SSR with hydration at the beginning, followed by CSR taking over. For feeds, SSR is faster for the initial display because the server can render the content first and then send it to the browser.
For example, Twitter’s engineering article “Improving performance on twitter.com” discussed how Twitter used SSR to render content on the server so tweets could be shown to users faster.
Beyond faster initial display, one of Twitter’s reasons for choosing server-side rendering was control. If rendering happens on the client, rendering performance is no longer fully under the engineering team’s control. Users with older devices will spend more time rendering on the client. If rendering mainly happens on the server, the team can at least optimize the rendering path on infrastructure it controls, instead of being completely constrained by user device performance.
However, if we only send SSR HTML and do not let JavaScript take over afterward, users may see posts earlier, but the page cannot easily support the interactions modern social products require: real-time likes, comments, sharing, expandable menus, and so on. After SSR sends rendered HTML to the browser, the page still needs hydration so it can become interactive. Once CSR takes over, the feed can support rich interactions while also enabling performance-friendly techniques such as pagination.
Progressive loading
In addition to SSR with hydration, progressive loading is another design technique that helps improve loading speed. Progressive loading means we do not load everything at the beginning. We load what is immediately needed first, and defer anything that is not immediately visible. This keeps the initial payload small and improves speed. There are several places where progressive loading applies to feed design.
First, as mentioned earlier, the industry commonly uses SSR with hydration. For the SSR part, we can go one step further and use streaming. We also introduced this in the article on frontend rendering strategies. In fact, feeds in Meta’s social products currently use this approach. If you open facebook.com, inspect the Network panel in developer tools, and select the initial document response, you can see the HTML file received when entering the page.
If you observe that HTML, you will notice that its content keeps growing because it is streamed in. With streaming SSR, the server does not need to wait until all content is rendered before responding to the frontend. It can render by section and send each section as soon as it is ready. Users usually see the top section first, so sending that section earlier improves perceived loading speed. If you are interested in the implementation details, the related React Conf talk is worth watching.
Most feeds also use skeleton loading. Before actual posts are rendered, the page shows the structure of the posts first. This usually creates a better experience than a generic spinning loading indicator. From a streaming perspective, the server can first send the rendered skeleton UI to the frontend, then send the actual posts once they are rendered.
There is one caveat. If the user has a fast network connection, showing a skeleton first and then immediately replacing it with real posts can cause a brief flash, which hurts the user experience. A common solution is to combine skeleton loading with timing logic. For example, set the skeleton’s opacity in CSS and only fade it in after a certain number of milliseconds. If the posts render before that threshold, the user never sees the skeleton, which avoids an annoying flicker.
Read more
Feeds have several other frontend performance optimization opportunities beyond the ones discussed above. The complete version is available in the E+ Growth Program topic article. If you want to go deeper on this topic, as well as backend development, software engineering, and AI engineering, you can join the E+ Growth Program.
Support ExplainThis
If you found this content valuable, please consider supporting our work with a one-time donation of whatever amount feels right to you through this Buy Me a Coffee page.
Creating in-depth technical content takes significant time. Your support helps us continue producing high-quality educational content accessible to everyone.