
How to Make an App Like Feedly

Building a content aggregation platform like Feedly is more engineering work than it first appears. RSS and Atom parsing is straightforward. The hard parts are feed discovery, deduplication, personalisation at scale, and keeping latency low when a user opens the app. This post breaks down the architecture decisions you'll actually face.
What Does Feedly Actually Do Under the Hood?
Feedly's core loop is simple: poll feeds, parse entries, store them, serve them to users based on subscriptions and reading history. The complexity is in the scale. Feedly reported over 15 million users at its peak. Even at a fraction of that, you're dealing with millions of feed URLs, each polled on its own schedule.
The system has four distinct concerns:
- Feed crawling and parsing
- Content storage and deduplication
- User preference modelling
- Client delivery (web, iOS, Android)
Each of these scales differently and fails differently. Design them as separate services from the start.
Feed Crawling
An RSS/Atom crawler is an HTTP client with scheduling logic. The naive version polls every feed every 15 minutes. That's wasteful. High-traffic feeds like the BBC news RSS update every few minutes. A personal blog might update once a month.
Use an adaptive polling strategy. Track the average publication interval per feed and adjust the crawl frequency accordingly. A feed with a 30-day average update interval doesn't need polling more than twice a day. Etag and Last-Modified headers let you skip downloading unchanged content entirely, which dramatically reduces bandwidth.
Tools worth using: Scrapy for Python-based crawlers, or a lightweight Go service if you want lower memory overhead per concurrent request. The Go net/http client handles 10,000+ concurrent connections on modest hardware.
Feed parsing has its own traps. feedparser (Python) handles most RSS 0.9x, RSS 2.0, Atom 1.0, and a fair amount of broken XML gracefully. Real-world feeds frequently have encoding errors, missing required fields, and non-standard date formats. Budget time for edge case handling.
Content Storage and Deduplication
You'll receive the same article multiple times. A feed might republish entries when corrected. Syndication means one piece appears across dozens of feeds. Deduplication is not optional.
The standard approach is to fingerprint each entry. Compute a hash over the canonical URL (after following redirects) and the title normalised to lowercase with whitespace collapsed. Store this hash in a Redis set or a Bloom filter before writing to the database. If the hash exists, skip the write.
For the primary store, PostgreSQL works well up to tens of millions of articles. Partition the articles table by ingestion date. Beyond 100 million rows, you'll want to think about Cassandra or a time-series-oriented store like TimescaleDB. The read pattern is almost always "give me articles for these feed IDs since this timestamp," which maps cleanly to a time-ordered index.
Full-text search is a separate problem. Elasticsearch or OpenSearch handles it well. Index the title, summary, and author. Don't index full article body text unless you specifically need it; it bloats the index without proportional search quality gain for this use case.
/// Not sure where to start?
Get the architecture before you commit
Tell us what you're building and we'll map the technical approach, stack, and rough timeline. No cost, no obligation, no sales call required.
How Do You Build the Personalisation Layer?
Feedly's "AI assistant" Leo is essentially a set of keyword and entity filters plus a trained relevance model. You can get 80% of the value with much less than that.
Start with explicit signals: which feeds a user subscribes to, how often they read from each feed, and which articles they save or share. These give you a per-user feed affinity score. Rank articles within a feed by recency first, then surface articles from high-affinity feeds before low-affinity ones.
Implicit signals come later. Track reading time per article (time between open and close events). Articles read for under 10 seconds are probably skipped. Articles read for over 60 seconds are likely relevant. Use these to build a lightweight collaborative filter using matrix factorisation, or plug in a pre-trained sentence embedding model like sentence-transformers with the all-MiniLM-L6-v2 model to compute article similarity. Group users by reading patterns and recommend articles popular among similar users.
Topic extraction is useful for filtering. spaCy's named entity recognition, or a fine-tuned BERT model, can tag articles with entities (companies, people, places) in under 50ms per article at inference time on CPU. This lets users set up entity-based filters without building a full recommendation engine on day one.
One honest caveat: recommendation systems require training data, and training data requires users. If you're launching with under 10,000 active users, a simple frequency-weighted feed ranking will outperform a half-trained ML model. Build the ML layer once you have enough signal.
What Does the Mobile and Web Client Architecture Look Like?
The client layer is where perceived performance lives. Users judge the app by how fast their feed loads, not by how elegantly you've partitioned your Cassandra keyspace.
Use offline-first architecture. On mobile (React Native or Flutter), cache the last 50 unread articles per feed in SQLite via Watermelon DB or Drift. On web, IndexedDB with Dexie.js. The app renders from cache immediately on open, then syncs with the server in the background. This gives you a sub-200ms time-to-first-content on repeat opens regardless of network conditions.
WebSockets or Server-Sent Events handle real-time updates. SSE is simpler and sufficient for a read-only stream of new article notifications. Reserve WebSockets for features that need bidirectional communication, like collaborative annotation.
| Feature | SSE | WebSockets |
|---|---|---|
| New article notifications | ✓ Sufficient | Overkill |
| Read/unread sync | ✓ Sufficient | Overkill |
| Collaborative annotation | Insufficient | ✓ Required |
| Infrastructure complexity | Low | Medium |
For the API layer, GraphQL is a reasonable choice here because clients have genuinely varied data needs (mobile wants minimal payloads, web wants richer metadata). A REST API works too, but you'll end up versioning endpoints or over-fetching. Use DataLoader to batch database queries and avoid N+1 problems on feed queries.
How Much Does It Cost to Build?
Rough team composition for a production-grade version:
- 1 backend engineer owning the crawler and ingestion pipeline
- 1 backend engineer owning the API and personalisation layer
- 1 mobile engineer (React Native or Flutter handles both platforms)
- 1 frontend engineer for the web client
- 1 ML engineer, part-time in early stages
Timeline to a functional MVP with basic subscription management, feed crawling, and mobile/web clients: 16 to 20 weeks with that team. A full personalisation layer with trained models adds another 8 to 12 weeks.
Infrastructure costs at 100,000 active users: roughly $1,500 to $2,500/month on AWS or GCP, depending on crawl frequency and caching strategy. The crawling fleet dominates the compute cost. Spot or preemptible instances cut that significantly.
Conclusion
The architecture of a Feedly-style app is mature and well-understood. The decisions that actually determine success are: how well you handle broken feeds, how quickly you surface relevant content, and how responsive the client feels. Get those three right and the rest is implementation detail.
If you're scoping this out, start by mapping your feed corpus size and expected user count. Those two numbers drive almost every infrastructure decision. If you want a second opinion on your architecture before committing to a build, the Sodio team is happy to review your design.
FAQ
How long does it take to build an app like Feedly? A functional MVP with feed subscriptions, crawling, and mobile/web clients takes 16 to 20 weeks with a team of four to five engineers. Adding a trained personalisation layer extends that by 8 to 12 weeks. Timelines compress significantly if you use existing open-source RSS parsing libraries and managed infrastructure rather than building from scratch.
What technology stack should I use? There's no single right answer, but a practical stack is: Go or Python for the crawler, PostgreSQL for article storage, Redis for deduplication and caching, Elasticsearch for search, and React Native or Flutter for mobile. This combination is well-documented, has strong library support, and scales to millions of users without exotic infrastructure.
How do you handle feed deduplication? Fingerprint each article by hashing a normalised version of its canonical URL and title. Store hashes in a Redis set or a Bloom filter and check before writing to the database. For syndicated content where the URL differs across sources, a similarity hash over the title text catches most duplicates that URL matching misses.
Is RSS still relevant in 2025? Yes. RSS and Atom remain the dominant structured feed formats. JSON Feed (version 1.1) is gaining adoption among developer-focused publishers. Most major news sites, podcasts, and blogs still publish RSS. The format is simple, stateless, and doesn't require API keys, which makes it operationally easier than scraping or platform-specific APIs.
When should I add ML-based personalisation? After you have at least 10,000 active users generating consistent reading signals. Before that threshold, a frequency-weighted ranking and user-defined topic filters will serve most users better than a model trained on insufficient data. Instrument your reading events from day one so the training data is there when you need it.
Have a project in mind? Contact Sodio Technologies to discuss your requirements and explore the right technology solution for your business.
/// Work with us
Talk to the engineers who'd build it
You'll get a technical scope, timeline and cost estimate from the people doing the work, not an account manager. In-house team, no subcontracting, since 2016.
