Nelly and Clyde having a Discord conversation.
Engineering & Developers

Supercharging Discord Mobile: Our Journey to a Faster App

Discord & React Native

Discord's desktop and mobile clients are built with React & React Native respectively. Using React enables our teams to ship features rapidly across different platforms, yet requires careful attention to performance optimization as there’s less margin for error.

Initially, we shied away from using React Native on Android due to performance concerns, but recent advances in Android device capabilities and the introduction of Hermes, React Native's new JavaScript engine, changed the landscape. This led us to transition our Android client to React Native in 2022.

While the switch came with performance trade-offs (particularly startup times on lower-end devices) we tackled these challenges by cutting our median startup times in half during 2023 – a story we'll detail in a future post.

Most recently, we've turned our attention to optimizing the things that people use the most, with a particular focus on power users who push Discord's capabilities to (and sometimes beyond) their limits. If you're reading this, you're probably one of 'em!

We Virtualized The Server List

Discord's server list component has been completely rewritten to address memory usage concerns. While most users join just a few servers, we support joining up to 100 servers for free users and 200 for Nitro subscribers.

Previously, the non-virtualized component kept all views and server icons (including animated ones) in memory... even when they weren't visible on screen. All of these servers add up, especially for our power users.

Our new virtualized implementation only keeps information about the servers that are visible in memory, and as a bonus, we had enough spare resources to level-up our drag-n-drop animations!

Results: Users with 100+ servers saw a 14% reduction in memory usage at  startup, and a 10% decrease in overall startup time.

We Optimized Discord's Native Chat Performance

We undertook a major performance optimization effort for Discord's chat list component. While the component was already fully native and only uses JavaScript to fetch message data, our profiling revealed several opportunities to enhance both loading times and scrolling performance.

  • We implemented recycling mechanisms for both Application Components (such as buttons) and Media Mosaics (when we show multiple images in a dynamic grid layout).
  • To reduce initial load times, we moved certain elements that aren't frequently used, such as spoilers and upload overlays to a lazy inflation loading style. We also improved the performance of binding media mosaics.
  • We improved the measurement speed of both Message Containers and Reactions.
  • We now pre-fill our recycling pool with common used chat list elements before the user even opens the chat.
A before-and-after comparison of chat scrolling performance.
Side by side comparison of Discord Chat List on Samsung Galaxy A03s

Results: Our users have seen up to a 60% reduction in slow frames, while older devices render significantly more frames than before. Additionally, our benchmarks show approximately 12% less memory usage in the chat list component. If slow frame rates give you a headache, you'll appreciate these fixes.

We Supercharged our Android Emoji Picker

Discord servers can pack quite the emoji punch, starting at 50 custom emojis for regular servers, going as high as 250 for fully-boosted ones. A typical phone screen can display around 150 emojis simultaneously, and in the most demanding scenarios, these could all be animated. (Or worse, they're all sent in a single message from the same guy. Thanks, Greg.)

This creates an interesting performance challenge, especially when users are rapidly scrolling through their emoji collection.

Going full native for Android

Discord's Android emoji picker faced a critical challenge: on lower-end devices, users would encounter completely blank frames while scrolling through their emojis. Not even placeholder images would appear, creating a bad experience in one of our core user flows.

Since our emoji picker implementation was pretty simple already, we quickly reached the conclusion that incremental optimizations wouldn't be enough to solve this.

We made a decision to rebuild the emoji picker natively for Android. This wasn't a choice we made lightly, as moving away from React Native meant maintaining separate codebases. However, the results justified the tradeoff.

After devising our new implementation, we stress-tested it with our most demanding scenario: a power user accessing emojis from 200 different servers. Our implementation not only eliminated the blank frames entirely but delivered consistently-smooth scrolling, even on budget devices where the old implementation would “blank” or even crash when running out of memory.

While this architecture split between Android (native) and iOS (React Native) increases our maintenance complexity, we believe the improved user experience is worth the cost. Looking ahead, we'll reassess this approach as we switch to React Native's New Architecture and as more powerful Android devices become the norm.

A before-and-after comparison of Android emoji picker performance.
Side by side comparison of Discord Emoji Picker on Samsung Galaxy A14

60FPS Animated WebP Emojis

Our media-serving team made a lot of performance optimizations in 2024, and one of them was adding animated WebP support for our media proxy!

Switching our animated emojis format from GIFs to WebP allowed low-end devices to render animated emojis at 60 fps.

A before-and-after comparison of animated WebP emoji performance.
Side by side comparison on Samsung Galaxy A14 showing higher frame rate with WebP

We plan to write a dedicated blog post about animated image support soon, so keep an eye out for it!

We Eliminated “Blanking” in our ChannelList

Discord has been using React Native for a while, and as such, we had our own home grown React Native List, AKA FastList. In 2023, we started using Shopify’s Flashlist as part of the new components we built while redesigning our mobile app, including our ChannelList. What we loved in FlashList was that we didn’t need to provide accurate element sizes, leading to a more ergonomic experiment and faster iterations.

Drake meme: "FastList" bad, "FlashList" good.
Drake meme: "FlashList" bad, "FastList" good.

However in retrospect we learned that FlashList was blanking more frequently on low end Android devices…so we went back for another round of refactoring, this time bringing back our own FastList and eliminated “blanking,” even on a $50 phone!

A before-and-after comparison of channel list performance.
Side by side comparison of Discord Channel List on Samsung A03s

Just to clarify - We still love FlashList and use it in lists where dynamic heights are too cumbersome to precompute.

FastList → FastestList

While rewriting our Emoji Picker, we created yet another React Native list, which we internally called FastestList.

Without getting too much into the technical weeds, the reason it's faster is because, unlike any other React Native lists out there, this list uses a native virtualized list, aka Android RecyclerView under the hood, not ScrollView (and not RecyclerListView).

This is combined with what we lovingly refer to as "View Portaling" which is a technique that allows native code to move around rendered JS views as they enter the viewport. This inversion of control which is normally antithetical to React itself (JS calls the shots, Native doesn't know any better) allows the component to understand when it has no rendered JSX views and thus needs to render a placeholder (instead of blanking until JS responds).

We then used our new FastestList and refactored multiple core flows to use it, including:

GIF Picker & Sticker Picker

Direct Message List

A before-and-after comparison of DM list performance.
Side by side comparison of Discord DM list on Samsung Galaxy A03

Server Member List

A before-and-after comparison of Server Member list performance.
Side by side comparison of Discord Member List on Samsung Galaxy A14

Now who on the team is going to build FasterestList?

The iOS Media Picker Stopped “Blanking” After Taking Photos

Usually we focus on Android performance, and iOS performance is presumed to be just as good, but that wasn’t the case with our iOS Media Picker. More specifically, we identified a noticeable “blanking” after multitasking to the system camera, taking photos and switching back to Discord and viewing our media picker.

We made two changes to improve this:

  1. We updated our implementation to support PHImageRequestOptionsDeliveryModeOpportunistic, using a low quality thumbnail while PhotoKit is working on a higher quality preview.
  2. Our original implementation was requesting high quality square previews at a resolution of 370x370, which loaded slowly. However, we found that requesting 256x256 hits a magic cache in PhotoKit, and returns almost instantly. The slightly lower thumbnail resolution was worth it for the big difference in loading speed.

Results: Eliminated 4.5 seconds of generating previews:

A before-and-after comparison of Media Picker performance.
Side by side comparison of Discord media picker on iPhone 16 Pro

What's cooking in 2025?

Our performance journey continues, with several exciting initiatives on the horizon. We're on the verge of enabling React Native's New Architecture in our stable builds, which will unlock the benefits of Faster Native interface and <Suspense> capabilities.

We're also making some big bets exploring static Hermes and an ambitious initiative to migrate our core stores and communication logic to Rust, with the goals of making the Discord app faster, making it run more smoothly, and reducing our overall memory footprint.

Additionally, we're strengthening our regression detection by expanding our CI test coverage and collecting more detailed metrics from each test run.

A huge shoutout to Alex, Amadeus, Athena, Joe, Miguel, Patrick, and Rhys for their incredible work on making Discord mobile faster than ever!

Passionate about making Discord faster? We have open positions in our Client Performance organization!

Tags
No items found.

related articles