Best Practices for Instagram-style Feeds

3 min read
Ian D.
Ian D.
Published November 17, 2016 Updated March 21, 2022


As part of our "best practices" series, we wanted to describe our best practices for setting up activity feeds for a simple photo sharing application. These feeds allow users to upload photos, follow other users, like photos, and see notification and aggregated feeds. Of course, how you use Stream depends greatly on the kind of application you're building and your intention for the data, so the best practices we define for this photo sharing application may not line up exactly with your project or business model. Feel free to reach out to our support team if you have questions. Regardless of your use case, our best practice when accessing user feeds is to utilize a UUID for identifying things in your app (users, photos, etc) to avoid collisions. For the sake of this blog post, the examples below will use usernames to make it easier to follow along. We created several feeds for our photo sharing app: two flat feeds, one aggregated feed and one notification feed.

Flat Feeds

This application uses two Flat feeds called "user" and "timeline". The "user" feed will store all photos that each individual user produces. We also hard-code a unique ID for a global feed where any user can see a public feed of all photos uploaded. For example, each photo that Nick uploads will be saved to both "user:global" and "user:nick". This also allows Nick to retrieve a feed of his own items, and also publishes his photo on the global feed for all other users to see. The "timeline" flat feed will allow someone to follow other "user" feeds so when viewing their timeline they'll see photos uploaded by their friends. For example, If Kevin wants to follow Josh, we would have Kevin's timeline feed ("timeline:kevin") follow Josh's user feed ("user:Josh"). Now, when the application retrieves Kevin's timeline feed ("timeline:kevin"), Stream will present a list of all photos that Josh has uploaded. We recommend blocking a user's timeline feed from following their own user feed, and also blocking users from seeing/following another user's timeline feed.

Aggregated Feeds

Aggregated feeds can be a little tricky. We wrote a blog post about de-mystifying their usage in September 2016. We set up a single aggregated feed called "timeline_aggregated", with an aggregation format using the actor, verb, and a timestamp of "YYYY-MM-DD" to allow for a daily roll-up of photos uploaded by someone you follow. {{actor}}_{{ }}_{{ time.strftime('%Y-%m-%d') }} To use this, Josh's aggregated timeline feed ("timeline_aggregated:josh") will follow Nick's flat "user" feed ("user:nick"). When Josh requests his aggregated feed, he will see an aggregated summary of every photo that Nick (and others whom Josh follows) took each day.

Notification Feeds

We have a single notification feed called "notification" on which we will track activities highlighting a "verb" such as "like" or "follow". This allows Thierry's notification feed to contain activities grouped by verb so he can see that a certain number of users "followed" him or "liked" one of his photos. To accomplish this, a like or follow event on the mobile app would post an activity where the "actor" was Kevin, the "verb" was "like" or "follow", and the activity is added to Thierry's notification feed ("notification:thierry") In our application, notifications about photo likes would appear like this:

Notifications about follows would appear like this:

When you post the "follow" activity, Stream will return the full activity payload back to you including a unique identifier that we generate; we recommend storing that activity ID in your database where you track which users follow one another or like a photo. If User A ever unfollows User B later or unlikes a photo, your backend can use this activity ID to post a removal of that activity from User B's notification feed so they no longer see the action ("verb") that User A performed.

Stay tuned for more

We'll be following this post with two more about a backend service in Go and an announcement of an Android example application which will showcase these feed practices. Follow us on Twitter for updates, or better yet sign up for our personalized RSS reader, Winds, and add our blog RSS feed!

Integrating Video With Your App?
We've built a Video and Audio solution just for you. Check out our APIs and SDKs.
Learn more ->