Browse Templates/News Feed App

News Feed App

A complete news feed database schema designed for content-driven applications and news aggregation platforms. Includes user profiles, article management with categories, threaded comment system, and bookmark/save functionality for personalized reading lists. Suitable for apps like Flipboard, Google News, or custom news reader solutions.

PostgreSQL5 tablesMobile
newscontentarticlesmobilesocial
Created with ERD Studio

About this schema

The schema is small on purpose: five tables covering publishing, reading and saving. articles carries a status and a published_at separate from created_at, which is what lets a draft exist for days before going live — and lets a scheduled piece be written now and appear later without a second table.

One users table serves both writers and readers, split by a role column. A news site has very few authors and very many readers, and the same person is often both, so separating them would duplicate accounts to express a distinction that one column already makes.

comments nests through parent_id and bookmarks is a plain pair of keys. Neither carries any cached count, which is the honest consequence of a schema this size: view_count on articles is the only aggregate kept, because it is the one number a listing sorts on.

Key relationships

categories → articles
Each article sits in one category. A flat list with sort_order rather than a tree, which suits a news site's fixed set of sections.
users → articles (author_id)
The byline. Keeping the author as a key rather than a text field means an author page is a query and a renamed writer updates everywhere.
articles → comments → comments (parent_id)
Replies nest through the self-reference. The article is the root, so a comment cannot exist without the piece it responds to.
users ↔ articles via bookmarks
A simple join with a timestamp. Read-it-later is a per-user list, which is why it is a table rather than a flag on the article.
articles.status / published_at
Two columns, not one. Status says whether it is live; published_at says when it went live and orders the front page.

Design decisions

published_at is separate from created_at

A single timestamp would make the front page order by when a draft was started, which is wrong for anything written in advance. Keeping both means the newsroom can order by publication while retaining the real authoring date, and a null published_at is an unambiguous not-yet-live state that no status string can contradict.

A slug column alongside the id

News URLs are read by people and ranked by search engines, so the address has to carry the headline rather than a number. Storing the slug means the canonical URL is a column rather than something regenerated from a title that might later be edited — which is what quietly breaks every inbound link when a headline is fixed after publication.

view_count is on the article, with no event table

A views table would support unique readers, referrers and time-of-day analysis, and would grow faster than every other table combined. A counter on the row answers the one question a news site actually sorts on — what is being read — at the cost of being an opaque number that cannot be broken down or recomputed.

Readers and authors share one table

role on users is enough to tell them apart, and it keeps commenting, bookmarking and writing on the same identity. The limitation shows up with guest contributors: an author who never logs in still needs a row, and an external byline has nowhere to go except an account that will never be used.

Tables in this template

usersUsers
6 cols
categoriesCategories
5 cols
articlesArticles
11 cols
commentsComments
6 cols
bookmarksBookmarks
4 cols

Frequently asked

How do I schedule an article for later?
Set published_at to a future time and have the front page filter on published_at being in the past. The status column then covers draft and archived, and no background job has to flip anything at the right moment.
Why is there no tags table?
Because categories are exclusive here — one article, one section — which fits a news site's navigation. Tags are the natural addition when articles start needing to appear under several topics at once.
Can comments be moderated?
Not with this schema as drawn. There is no status or removal flag on comments, so hiding one means deleting it — which also drops its replies. A status column is the first thing to add before opening comments publicly.
Where would a paywall live?
Nowhere yet. It needs an access level on the article and a subscription table for readers, since a paywall is a question about the reader and the piece at the same time.
Does bookmarks need its own id column?
Not strictly — the user and article pair is unique and could be the primary key. The surrogate id is kept for consistency with the other tables, but the unique constraint on the pair is what actually prevents saving the same article twice.