Photo Sharing ER diagram and database schema
The Photo Sharing database schema is a DB Planner template with 28 tables, 192 columns and 60 relationships, free to use. Core tables include blocks, close_friends, collection_posts, collections. It can be opened as an interactive ER diagram or exported as PostgreSQL, MySQL, or SQL Server DDL.
- Tables
- 28
- Columns
- 192
- Relationships
- 60
- Category
- Social
- Exports
- DBML, SQL, C#
- Price
- Free
What this schema models
A complete photo sharing app database design, the kind of data model behind an app similar to Instagram: 28 tables, 13 enums and 60 relationships covering accounts, profiles and follows (with requests for private accounts), carousel posts with media variants, hashtags, mentions and photo tags, likes, threaded comments and saved collections, expiring stories with views and highlights, notifications and push devices, and blocks, mutes, reports and moderation actions. THE FOUR DESIGN RULES 1. Counters are caches; rows are the truth. Like, comment, follower and hashtag counts are denormalized for fast feeds and profile headers, but post_likes, comments, follows and post_hashtags are authoritative. Each cache is incremented in the same transaction and reconciled by a background job; when the two disagree, the rows win. 2. A post is a container, media are files. The post holds the caption and settings; each photo or video is an ordered post_media row (that is all a carousel is), with resized and transcoded variants by storage key. Bytes never live in the database, and a phone on a slow network never downloads the original. 3. A follow request is a state, not a separate table. Following a private account inserts the same follows row in state pending; approving is an UPDATE, and every visibility check reads only accepted rows. 4. Expiry and removal are timestamps, not deletes. Stories carry expires_at and feeds filter on it, so an expired story can still go into a highlight. Moderators never hard-delete: posts, comments and stories point at the moderation action that removed them, and a successful appeal is a new action that reverses it. DETAILS WORTH STEALING - Photo tags store x and y as fractions of the image (0 to 1), so a tag lands on the same spot in every resized variant. - Hashtags are derived from the caption on every save: the caption is the source, post_hashtags is its index. - Replies are one level deep: replying to a reply points at the same top-level comment and mentions the person. - Collections are folders over saves, joined by a composite foreign key that cascades, so unsaving removes a post from every collection at once. - Notifications carry a group_key, so "sam and 41 others liked your post" is grouped at read time and an undone like deletes exactly its own row. - Blocks are indexed in both directions because every read path checks both; a mute is a quiet unfollow the muted person never sees. WHAT YOU GET Clean DBML that imports directly into DB Planner, and a laid-out board with zones color-coded and framed: accounts and follows, posts and media, engagement, stories, notifications, and trust and safety. Every table carries a note. Postgres-flavoured types that port cleanly to MySQL or SQL Server. Useful for developers building a photo sharing or social media app, and for students who need a realistic photo sharing app ER diagram for a DBMS project. This is a schema design reference; feed ranking, media processing and content policy belong in your own services.
Tables (28)
| Table | Columns |
|---|---|
| blocks | 3 |
| close_friends | 3 |
| collection_posts | 4 |
| collections | 5 |
| comment_likes | 3 |
| comments | 12 |
| follows | 5 |
| hashtags | 5 |
| highlight_stories | 3 |
| highlights | 6 |
| media_variants | 8 |
| mentions | 5 |
| moderation_actions | 13 |
| mutes | 5 |
| notifications | 10 |
| photo_tags | 6 |
| places | 7 |
| post_hashtags | 3 |
| post_likes | 3 |
| post_media | 11 |
| posts | 13 |
| profiles | 11 |
| push_devices | 7 |
| reports | 12 |
| saves | 3 |
| stories | 13 |
| story_views | 3 |
| users | 10 |
Relationships (60)
blocks.blocked_id references users.idmany to oneblocks.blocker_id references users.idmany to oneclose_friends.friend_id references users.idmany to oneclose_friends.owner_id references users.idmany to onecollection_posts.collection_id references collections.idmany to onecollection_posts.user_id references saves.user_idmany to onecollections.cover_post_id references posts.idmany to onecollections.owner_id references users.idmany to onecomment_likes.comment_id references comments.idmany to onecomment_likes.user_id references users.idmany to onecomments.author_id references users.idmany to onecomments.parent_comment_id references comments.idmany to onecomments.post_id references posts.idmany to onecomments.removed_by_action_id references moderation_actions.idmany to onefollows.followee_id references users.idmany to onefollows.follower_id references users.idmany to onehighlight_stories.highlight_id references highlights.idmany to onehighlight_stories.story_id references stories.idmany to onehighlights.owner_id references users.idmany to onemedia_variants.post_media_id references post_media.idmany to onementions.comment_id references comments.idmany to onementions.mentioned_user_id references users.idmany to onementions.post_id references posts.idmany to onemoderation_actions.comment_id references comments.idmany to onemoderation_actions.moderator_id references users.idmany to onemoderation_actions.post_id references posts.idmany to onemoderation_actions.report_id references reports.idmany to onemoderation_actions.reverses_action_id references moderation_actions.idmany to onemoderation_actions.story_id references stories.idmany to onemoderation_actions.target_user_id references users.idmany to onemutes.muted_id references users.idmany to onemutes.muter_id references users.idmany to onenotifications.actor_id references users.idmany to onenotifications.comment_id references comments.idmany to onenotifications.post_id references posts.idmany to onenotifications.recipient_id references users.idmany to onenotifications.story_id references stories.idmany to onephoto_tags.post_media_id references post_media.idmany to onephoto_tags.tagged_user_id references users.idmany to onepost_hashtags.hashtag_id references hashtags.idmany to onepost_hashtags.post_id references posts.idmany to onepost_likes.post_id references posts.idmany to onepost_likes.user_id references users.idmany to onepost_media.post_id references posts.idmany to oneposts.author_id references users.idmany to oneposts.place_id references places.idmany to oneposts.removed_by_action_id references moderation_actions.idmany to onepush_devices.user_id references users.idmany to onereports.comment_id references comments.idmany to onereports.post_id references posts.idmany to onereports.reported_user_id references users.idmany to onereports.reporter_id references users.idmany to onereports.story_id references stories.idmany to onesaves.post_id references posts.idmany to onesaves.user_id references users.idmany to onestories.author_id references users.idmany to onestories.removed_by_action_id references moderation_actions.idmany to onestory_views.story_id references stories.idmany to onestory_views.viewer_id references users.idmany to oneusers.id references profiles.user_idone to one
How to use this template
- Open the ER diagram to see the tables and how they relate.
- Copy it into your workspace. You get your own editable copy, in DBML.
- Export it as PostgreSQL, MySQL, or SQL Server DDL, or as C# models.
The copy opens in DB Planner’s ER diagram tool, with the schema as text in the DBML editor beside it. Have a database already? Turn its SQL into an ER diagram instead.
Frequently asked questions
- What is in the Photo Sharing database schema?
- 28 tables and 60 relationships, across 192 columns. The table names and the full relationship list are shown on this page.
- Can I export it to PostgreSQL or MySQL?
- Yes. Every DB Planner template exports as DBML, as PostgreSQL, MySQL, or SQL Server DDL, and as C# models.
- Is this template free?
- Yes. You can open it in the browser without an account, and copy it into your own workspace with a free DB Planner account.
- Can I change it after copying it?
- Yes. A copy is yours: you can rename tables, add columns, and export it. Changes the author makes later do not affect your copy.