Develop a Photo Sharing Platform like Flickr or Google Photos
Let's look into fr
FR
1.Support uploading single images and batches (albums), with progress/resume for large files.
2.Detect identical files (hash) to avoid duplicate storage while keeping separate user metadata if needed.
3.Extract EXIF (timestamp, camera, GPS, orientation), compute perceptual hashes (pHash) for visual similarity.
4.Images (jpg, png, webp, heif), videos (mp4, mov) with size/type validation.
5.Store original files plus generated derivatives: thumbnails, web-optimized, various resolutions.
6.Preserve original when user edits (crop/filters) and keep version history.
7.Search by date range, location, camera model, tags, people (if enabled), and visual similarity
8.Generate shareable links with optional expiration and password protection.
NFR
1.System should be highly scalable to handle hundreds of millions of users and billions of photos.
2.System should be highly available
3.Upload latency: initial response within <500ms, total upload time dominated by network speed.
Photo viewing latency: <200ms for cached thumbnails, <1s for full-resolution image fetch.
4 . Metadata consistency: Strong consistency for per-user views (newly uploaded photo should appear instantly).
Eventual consistency acceptable across replicas and derived services (search index, AI tagging).
Back of envelope calculation
API’s
1. Authentication & User Management
1.1 POST /api/v1/auth/signup
Purpose: Register a new user (email/password or OAuth).
Request:
{
“email”: “user@example.com”,
“password”: “securePass”,
“name”: “John Doe”
}
Response:
{
“userId”: “u123”,
“message”: “Signup successful. Verification email sent.”
}
1.2 POST /api/v1/auth/login
Purpose: Authenticate user and return access token.
Request:
{
“email”: “user@example.com”,
“password”: “securePass”
}
Response:
{
“accessToken”: “jwt-token”,
“refreshToken”: “refresh-token”,
“expiresIn”: 3600
}
1.3 POST /api/v1/auth/refresh
Purpose: Refresh access token.
Request: { “refreshToken”: “refresh-token” }
Response: { “accessToken”: “new-jwt”, “expiresIn”: 3600 }
2. Photo Upload & Management
2.1 POST /api/v1/photos/upload-url
Purpose: Generate signed URL for direct upload to storage (S3/GCS).
Request:
{
“fileName”: “vacation1.jpg”,
“contentType”: “image/jpeg”
}
Response:
{
“uploadUrl”: “https://s3.amazonaws.com/bucket/xyz?signature=...”,
“photoId”: “p123”,
“expiresIn”: 900
}
2.2 POST /api/v1/photos/complete
Purpose: Notify backend that upload finished; triggers thumbnail & metadata extraction.
Request:
{
“photoId”: “p123”,
“size”: 4215934,
“checksum”: “a1b2c3d4”,
“exif”: {
“camera”: “Pixel 8”,
“timestamp”: “2025-10-13T12:03:45Z”,
“gps”: { “lat”: 28.6, “lng”: 77.2 }
}
}
Response:
{ “status”: “processing” }
2.3 GET /api/v1/photos/{photoId}
Purpose: Fetch photo metadata + URLs for different resolutions.
Response:
{
“photoId”: “p123”,
“ownerId”: “u123”,
“title”: “Sunset”,
“urlOriginal”: “https://cdn.domain/photos/p123/original.jpg”,
“urlMedium”: “https://cdn.domain/photos/p123/medium.jpg”,
“urlThumb”: “https://cdn.domain/photos/p123/thumb.jpg”,
“tags”: [”sunset”,”beach”],
“createdAt”: “2025-10-12T10:45:32Z”,
“visibility”: “private”
}
2.4 DELETE /api/v1/photos/{photoId}
Purpose: Soft-delete or permanently delete photo.
Response: { “message”: “Photo moved to trash” }
2.5 PATCH /api/v1/photos/{photoId}
Purpose: Update title, tags, visibility, or description.
Request:
{
“title”: “Goa Beach”,
“tags”: [”goa”,”sea”],
“visibility”: “public”
}
Response: { “message”: “Photo updated” }
2.6 GET /api/v1/users/{userId}/photos
Purpose: Paginated list of user’s photos.
Response:
{
“photos”: [
{”photoId”: “p1”,”thumb”:”...”,”title”:”...”},
{”photoId”: “p2”,”thumb”:”...”,”title”:”...”}
],
“nextCursor”: “eyJwYWdlIjoyfQ==”
}
3. Album Management
3.1 POST /api/v1/albums
Purpose: Create a new album.
Request:
{
“title”: “Trip to Manali”,
“description”: “Memories from 2025”,
“visibility”: “private”
}
Response:
{ “albumId”: “a123” }
3.2 POST /api/v1/albums/{albumId}/photos
Purpose: Add photos to album.
Request: { “photoIds”: [”p1”,”p2”,”p3”] }
Response: { “added”: 3 }
3.3 GET /api/v1/albums/{albumId}
Purpose: Get album details with photo previews.
Response:
{
“albumId”: “a123”,
“title”: “Trip to Manali”,
“photos”: [
{”photoId”:”p1”,”thumb”:”...”},
{”photoId”:”p2”,”thumb”:”...”}
],
“sharedWith”: [”u456”],
“visibility”: “shared”
}
3.4 PATCH /api/v1/albums/{albumId}
Purpose: Edit album title/description/visibility.
3.5 DELETE /api/v1/albums/{albumId}
Purpose: Delete or archive album.
4. Search & Discovery
4.1 GET /api/v1/search
Purpose: Search photos by tag, title, EXIF data, or AI tags.
Query params:
?query=sunset&location=goa&from=2025-01-01&to=2025-12-31
Response:
{
“results”: [
{”photoId”:”p123”,”thumb”:”...”,”title”:”Sunset in Goa”},
{”photoId”:”p567”,”thumb”:”...”,”title”:”Evening Beach”}
],
“count”: 2
}
4.2 GET /api/v1/tags/trending
Purpose: Return trending user or system tags.
Response: { “tags”: [”sunset”,”mountain”,”friends”] }
5. Sharing & Collaboration
5.1 POST /api/v1/photos/{photoId}/share
Purpose: Generate shareable link or grant access to user(s)
Request:
{
“shareType”: “link”, // “link” | “user”
“expiry”: “2025-12-31T00:00:00Z”,
“password”: “optional”
}
Response:
{
“shareUrl”: “https://photos.app/share/abc123”,
“expiresInDays”: 30
}
5.2 GET /api/v1/shares/{shareId}
Purpose: View shared photo or album details (no login if public link).
5.3 POST /api/v1/albums/{albumId}/collaborators
Purpose: Add collaborators (can add photos/comments).
Request: { “userIds”: [”u456”,”u789”], “permissions”: “upload” }
Response: { “added”: 2 }
5.4 GET /api/v1/albums/shared-with-me
Purpose: Get albums shared with the current user.
6. Comments & Reactions
6.1 POST /api/v1/photos/{photoId}/comments
Purpose: Add comment to photo.
Request: { “text”: “Awesome click!” }
Response: { “commentId”: “c123”, “createdAt”: “...” }
6.2 GET /api/v1/photos/{photoId}/comments
Purpose: Fetch comments for a photo.
6.3 POST /api/v1/photos/{photoId}/like
Purpose: Like or unlike photo.
Response: { “likes”: 120 }
7. AI & Tagging Services
7.1 GET /api/v1/photos/{photoId}/tags/auto
Purpose: Get auto-generated tags (ML-based).
Respon
{
“photoId”: “p123”,
“autoTags”: [”beach”,”sea”,”people”],
“confidence”: [0.94, 0.91, 0.87]
}
7.2 POST /api/v1/photos/{photoId}/tags/confirm
Purpose: User confirms or rejects auto-tags.
8. Notifications
8.1 GET /api/v1/notifications
Purpose: List user notifications.Response:{
“notifications”: [
{”id”:”n1”,”type”:”comment”,”text”:”Alice commented on your photo”,”read”:false},
{”id”:”n2”,”type”:”share”,”text”:”Bob shared an album with you”,”read”:true}
]
}
Databases
| Module | DB Type | Example DB | Purpose |
| ------------------------------------ | ---------------- | ------------------------------ | ---------------------------- |
| Users, Auth, Albums, Photos Metadata | Relational (SQL) | **PostgreSQL / MySQL** | Strong consistency & joins |
| Photos (binary data) | Object Storage | **Amazon S3 / GCS / MinIO** | Store actual images |
| Search (tags, captions, AI labels) | Search Index | **Elasticsearch / OpenSearch** | Fast text/tag-based queries |
| Comments, Likes | NoSQL (Document) | **MongoDB / DynamoDB** | High write throughput |
| Notifications | Cache / Stream | **Redis Streams** | Fast ephemeral feed |
| Analytics | Columnar | **ClickHouse / BigQuery** | Aggregate user & photo stats |
🧍 USERS TABLE
DB: PostgreSQL
CREATE TABLE users (
user_id BIGSERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255),
profile_pic_url TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
🔐 AUTH TOKENS
DB: PostgreSQL
CREATE TABLE auth_tokens (
token_id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(user_id),
access_token TEXT NOT NULL,
refresh_token TEXT NOT NULL,
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
🖼️ PHOTOS METADATA
DB: PostgreSQL
Stores only metadata, not the image binary.
CREATE TABLE photos (
photo_id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(user_id),
title VARCHAR(200),
description TEXT,
original_url TEXT,
medium_url TEXT,
thumb_url TEXT,
size BIGINT,
checksum CHAR(32),
visibility VARCHAR(10) CHECK (visibility IN (’public’, ‘private’, ‘shared’)),
exif JSONB, -- camera, gps, etc.
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
🏷️ TAGS
DB: PostgreSQL (or Elasticsearch for fast tag search)
CREATE TABLE tags (
tag_id BIGSERIAL PRIMARY KEY,
tag_name VARCHAR(100) UNIQUE
);
PHOTO_TAGS (many-to-many)
CREATE TABLE photo_tags (
photo_id BIGINT REFERENCES photos(photo_id),
tag_id BIGINT REFERENCES tags(tag_id),
PRIMARY KEY (photo_id, tag_id)
);
📚 ALBUMS
DB: PostgreSQL
CREATE TABLE albums (
album_id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(user_id),
title VARCHAR(200),
description TEXT,
visibility VARCHAR(10) CHECK (visibility IN (’public’, ‘private’, ‘shared’)),
cover_photo_id BIGINT REFERENCES photos(photo_id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
ALBUM_PHOTOS (many-to-many)
CREATE TABLE album_photos (
album_id BIGINT REFERENCES albums(album_id),
photo_id BIGINT REFERENCES photos(photo_id),
PRIMARY KEY (album_id, photo_id)
);
👥 SHARES
DB: PostgreSQLCREATE TABLE shares (
share_id BIGSERIAL PRIMARY KEY,
resource_type VARCHAR(20) CHECK (resource_type IN (’photo’, ‘album’)),
resource_id BIGINT NOT NULL,
shared_by BIGINT REFERENCES users(user_id),
shared_with BIGINT REFERENCES users(user_id),
permissions VARCHAR(20) CHECK (permissions IN (’view’, ‘edit’, ‘upload’)),
expiry TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
💬 COMMENTS
DB: MongoDB Collection: comment
{
“comment_id”: “c123”,
“photo_id”: “p123”,
“user_id”: “u456”,
“text”: “Beautiful shot!”,
“created_at”: “2025-10-13T10:00:00Z”
}
❤️ LIKES
DB: MongoDB Collection: likes
{
“photo_id”: “p123”,
“user_id”: “u456”,
“created_at”: “2025-10-13T10:02:00Z”
}
🔔 NOTIFICATIONS
DB: Redis Stream (or MongoDb)
{
“notification_id”: “n789”,
“user_id”: “u123”,
“type”: “comment”,
“message”: “Alice commented on your photo”,
“is_read”: false,
“created_at”: “2025-10-13T10:10:00Z”
}
Microservices and their interaction
⚙️ Photo Sharing Platform — Microservices & Interactions
| Service | Description | DB / Dependencies |
| ------------------------------ | ------------------------------------------------------------ | -------------------------- |
| **Auth Service** | Handles signup, login, token issuance, OAuth | PostgreSQL |
| **User Service** | Manages user profiles, settings | PostgreSQL |
| **Photo Service** | Handles photo upload metadata, visibility, and links | PostgreSQL, S3 |
| **Upload Service** | Generates pre-signed URLs, handles multipart uploads | S3 / GCS |
| **Processing Service** | Generates thumbnails, extracts EXIF, and triggers AI tagging | Kafka, S3 |
| **Tagging / AI Service** | Adds auto-tags using ML models | PostgreSQL / Elasticsearch |
| **Album Service** | Groups photos, manages sharing and collaboration | PostgreSQL |
| **Share Service** | Manages photo/album sharing links and permissions | PostgreSQL |
| **Comment Service** | Handles comments and likes | MongoDB |
| **Notification Service** | Sends in-app and push notifications | Redis Streams |
| **Search Service** | Indexes photos/tags for discovery | Elasticsearch |
| **Analytics Service** | Tracks views, likes, trends | ClickHouse |
| **Admin / Moderation Service** | Reviews reported photos, handles NSFW filtering | PostgreSQL |
| **Gateway / API Aggregator** | Entry point for all client calls; routes to microservices | — |
| **CDN / Object Storage** | Serves optimized image versions globally | S3 / CloudFront |
🧭 Service-to-Service Interaction Flow
🟢 1. User Registration & Login
Client → Auth Service:
/signupor/loginAuth Service → User Service: create user record
Auth Service: issues JWT tokens
🟠 2. Photo Upload Flow
Client → Upload Service:
POST /photos/upload-urlUpload Service: returns pre-signed S3 URL
Client → S3: uploads file directly
Client → Photo Service:
POST /photos/completePhoto metadata saved to PostgreSQL
Photo Service → Kafka: emits
photo.uploadedeventProcessing Service (consumer):
Downloads image from S3
Extracts EXIF metadata
Generates thumbnails (stored back in S3)
Emits
photo.processedevent
Tagging / AI Service (consumer):
Detects objects, faces, locations
Stores tags in photo_auto_tags table + Elasticsearch index
Emits
photo.taggedevent
Notification Service: notifies user “Photo processed and ready!”
🔵 3. Album Creation & Sharing
Client → Album Service:
POST /albumsCreates record in PostgreSQL
Client → Album Service: add photos (
POST /albums/{id}/photos)Client → Share Service: share album with users or via public link
Generates unique share token
Share Service → Notification Service:
Sends notification to invited users
🟣 4. Comments & Likes
Client → Comment Service:
POST /photos/{id}/commentsStored in MongoDB
Comment Service → Notification Service:
Sends “User X commented on your photo”
Client → Comment Service:
POST /photos/{id}/likeComment Service → Analytics Service:
Emits
photo.likedevent to ClickHouse
🟠 5. Search & Discovery
Client → Search Service:
GET /search?query=sunsetSearch Service → Elasticsearch: full-text search on tags/titles
Search Service: merges AI tags + metadata from Photo Service for response
🔴 6. Notification Delivery
Notification Service: consumes all events (
photo.shared,photo.commented, etc.)Redis Streams / Kafka → WebSocket Gateway: pushes real-time updates to users
User sees new notification in app instantly
⚫ 7. Admin / Moderation
Processing Service: flags NSFW content using ML model
Admin Service: reviews flagged content, deletes or bans if needed
Admin → Notification Service: notifies user about moderation action
⚪ 8. Analytics & Trends
Every view/like event → Analytics Service (ClickHouse)
Periodic jobs compute:
Most viewed photos
Trending tags
Active users
Aggregated data can be displayed on Explore Page via Search Service.
┌──────────────────┐
│ API Gateway │
└────────┬─────────┘
│
┌──────────────┼────────────────────────┐
│ │ │
Auth/User Photo/Upload Album/Share
Service Service Service
│ │ │
│ ▼ │
│ Processing Service │
│ │ │
│ ▼ ▼
│ Tagging Service Notification Service
│ │ │
│ ▼ ▼
│ Search Service Comment Service
│ │ │
│ ▼ ▼
│ Analytics Service Redis / WebSocket
│
▼
Admin / Moderation Service
HLD


