I found Reddit’s iOS app experience better than the web version, so I thought of checking how it loads data so fast. Here is the teardown of Reddit’s iOS app.
Here are some highlights:
- It uses Token-based authentication.
- It uses GraphQL APIs for almost everything from configuration & experiments to post info.
- It monitors the performance of its API system as experienced by its users using an API named w3-reporting.
- In most of the GraphQL API calls only the operation name is passed without variables, I am assuming they are using middleware to abstract the configuration of the variables from front-end. A backend service is filling in info based on the operation name.
- Reddit uses Web Socket for the live comments feature.
Here is the detailed teardown of the API calls. I used Requestly’s Desktop App to intercept Reddit’s iOS app, setup instructions are provided here.
Technology Used
Reddit App is created with
- Reddit’s iOS app uses GraphQL APIs to load all the content.
- Token-based authentication is used for validating users.
- Performance Monitoring by reporting the API performance at the user end.
- Live commenting is supported using WebSocket.
- Dynamic Configuration to remotely control app behaviour without deploying new versions.
- Dynamic Experiments to remotely control experiments, not needing new deployment to change the status of an experiment.
Better UX with Preloading
The main question I had was how the app is performing so fast was answered upon checking FeedPostDetailsByIds API’s response. This API is called on the home screen with the ids of the posts shown and comes with detailed info that is shown after clicking the post. This preloading of the top posts helped in instantly showing the post details screen without any loader.
- Preloading posts are shown on the feed.
- The response time of the APIs is also very fast.
GraphQL APIs Security
GraphQL queries consist of the data and structure of the response needed. The operation name is generally optional. Most Reddit APIs have only operation names in the queries and variables are available only when there are on-screen variables/filters like feed with hot and latest post options.
This gives less control to frontend developers to make changes independently but more control over misuse of the APIs to fetch unnecessary data after all its user-facing API.
Remote Controlled Experiments
Running experiments on native iOS apps is difficult it needs re-deployments to enable or disable experiments, but Reddit has set-up the app in such a way that experiments can be controlled remotely. All the experiments are loaded in an API along with their values and statuses. The app automatically activates the variant of the experiment it assigned.
Flag-based Features Control
With so many users, experiments and features it's better to control them remotely. Reddit does a great job of controlling these features remotely.
At every launch of the app, it will call a configuration API to load 400+ configuration variables. Based on these variables it shows different features and variants of the features.
Secret of Karmas
The API with the operation name GetTopKarmaSubreddits
gets the list of top subreddits with karma points earned in each. This API reveals how many comments and post karma we have gained from our activity in each sub-reddit. I could never find this information inside Reddit’s web and mobile UI.
Scope of Improvement
While reading the APIs to find what type of data it brings, I found SubredditFeedElements
API loads the feed of the selected sub-reddit but with each post, it has a nested JSON of detailed sub-reddit information. This information is redundant and can be removed to reduce the network load of the API and further improve its performance.
Note: SubredditFeedElements
API is now replaced by SubredditFeedSdui
API and issue is fixed.
Use AI for Insights
I tried using ChatGPT to get some insights from the APIs. So created a file with all the APIs with their curl and their responses in it. Uploaded this file to a CustomGPT so that I can put any type of query. It gave some insights that were evident like what type of use an API might have and the structure of the response but it hallucinated a lot, most likely due to lots of APIs or I am no expert in prompting. Some of the insights given by AI:
GetAllExperimentVariants
API — Many experiments have specific "variant" names, including options likeenabled
,variant_1
,control_model
, andone_feed_ph_bridge_new_users
. This segmentation suggests that Reddit is testing features on particular user segments to determine their impact. For example, the experimentd2x_avatar_in_comments_loggedin
has two variants,loggedin
, andloggedout
, potentially testing the feature based on the user authentication state.GetAllExperimentVariants
API — Experiments includehybrid_video_rollout_android_v2
,active_sales
, andgql_google_maps_integration
, which point to a wide range of feature tests covering video functionality, ad placements, user interface enhancements, and third-party integrationsGetAccountDetails
API — The API response contains various fields detailing the user’s account status, such asisSubredditCreationAllowed
,isNameEditable
,isPasswordSet
, and the user's moderator status. Additionally, it includessuspensionExpiresAt
andisSuspended
, which indicate if an account is currently suspended or restricted
List of APIs
There are the list of GraphQL APIs I studied to understand how Reddit works. There were some other APIs as well like authentication, reporting etc. I didn’t include them in this list.
Screen |
GraphQL API |
Description |
---|---|---|
Home |
GetAllDynamicConfigs |
Loads 400+ config parameters based on which different features of the app works. The configuration is in typical key value format along with type of the value which can be a JSON, float, string etc. |
|
GetAllExperimentVariants |
The Request contains information about the app and device to assign experiments meant for the device and app version. Response contains a list of all the experiments with id, experimentName, version & status. |
|
GetAccount |
Loads all the details of the logged in user. |
|
HomeFeedSdui |
Loads the first few posts with minimum details to show on homepage. |
|
FeedPostDetailsByIds |
Preloads the posts using ids with all the details, in case a user clicks on the post. |
|
DiscoverBarRecommendations |
Discover bar data. |
|
UserPremiumSubscription |
Data related to user premium subscription |
|
GetUserAdEligibility |
Gets the ad eligibility of the user and any preferences. |
|
BadgeCounts |
Information about the badges earned by the user. |
|
|
|
Subreddit Page |
SubredditChannels |
Loads all the basic details about the community like description, icons, counters, allowed post types, and colours. |
|
SubredditTaxonomyTopics |
Loads the category of the community and a display text like if I load the community r/software it will show #20 in Software & Apps. |
|
IsInvitePending |
As the name suggests check for a pending invite, but not sure exactly which invite. |
|
SubredditChannels |
Loads the chat channels of the sub-reddit, I checked many subreddits but couldn’t find any. |
|
BlockedRedditors |
Brings data if user is blocked. |
|
GetModerators |
Gets the list of mods. |
|
FetchStructuredStyleAndWidgets |
This API brings info about style, rules and details of the community. |
|
FetchRelatedCommunityRecommendations |
This API brings related communities. |
|
SubredditMuting |
Checks if sub reddit is muted. |
|
SubredditFeedElements |
Loads the feed of sub-reddit. It takes the filters & layout options selected for the sub-reddit. Brings in all the details about posts to be displayed in feed. |
|
PostInfoByIdComments |
This request preloads the comments of the first post only. |
|
|
|
Post Page |
GetCustomEmojisStatus |
This API was called with the sub-reddit id and loads the status of custom emojis on sub-reddit. Its not very clear about why this API is called, but I have seen it on many occasions. The response was |
|
GetSubredditAchievementFlairsStatus |
Similar to emoji status it takes sub-reddit id and gets a response as isEnabled: false . The purpose of this is not clear to me. |
|
PostInfoByIdComments |
This API is used to load comments of the post by using post id passed in the request. |
|
CommentsPageAds |
Loads the ad just above the comments. |
|
|
|
Profile Page |
RedditorByName |
Loads the profile details of the logged in user. |
|
PostSetSettings |
Number of posts to load. |
|
GetTopKarmaSubreddits |
Get the list of top subreddits with karma points on each community, this API reveals about how many comment and post karma we have earned from our activity in each sub-reddit. |
|
UserProfileFeed |
The feed for user profile containing comments and posts. |
|
UserPublicTrophies |
List of achievements and trophies earned by the user name passed in request with id, name and image to be displayed. |
|
TippingProfileMigrated |
Details about the tipping profile, haven’t used this feature much. It showed 0 balance on my profile 😄. |
Conclusion
I would like to make couple of points in conclusion of this tear down experiment.
- Reddit’s APIs are not very fast instead they use preloading to give a better user experience.
- APIs work is never complete, even Reddit’s engineer have some work to do to further improve it.
- Keeping app & experiment configurations remotely can give a good control over user experience.
- Requestly’s engineers did a great job in showing operation name with each GraphQL Request, making life of devs much easier.