Skip to main content

Trade-offs & Future Work

Design trade-offs

1. JWT stored in LocalStorage

Decision: Store access and refresh tokens in LocalStorage.

Details
ProsSimple implementation; works seamlessly in a SPA without backend cookie configuration
ConsTokens are readable by JavaScript; vulnerable if an XSS attack is successful
MitigationsInput sanitization, React's default HTML escaping, short-lived access tokens, refresh token rotation
Planned improvementMove refresh token to an HttpOnly Secure cookie; the access token can remain in memory (not LocalStorage) for further hardening

2. Fan-out on read (following feed)

Decision: Generate the following feed by querying posts whose authorId is in the user's following list at read time.

Details
ProsSimple to implement; no write amplification; always fresh data
ConsQuery cost grows linearly with the size of the following list; can be slow for users who follow many accounts
Current mitigationCompound indexes on (authorId, createdAt) and (followerId)
Planned improvementCursor-based pagination to limit query scope; precomputed timelines (fan-out on write) for heavy users

3. Denormalized like/reply counts

Decision: Store likeCount and replyCount as fields directly on the Post document.

Details
ProsFast reads; no need to count related documents on every post fetch
ConsWrite contention on popular posts; risk of count drift if updates are not atomic
MitigationUse atomic increment/decrement operations ($inc) to keep counts consistent
AlternativeCompute counts on read from the Like and Reply collections (simpler, but slower at scale)

4. Monorepo vs separate repos

Decision: (Assumed) frontend and backend live in the same private repository for simplicity.

Details
ProsEasier to coordinate changes across frontend and backend; single CI pipeline
ConsTighter coupling; shared deployment pipeline
Planned improvementSeparate repos (or at minimum separate CI jobs) if the project grows to a team setting

5. No automated test suite (MVP stage)

Decision: Manual testing only at MVP stage.

Details
ProsFaster initial development cycle
ConsHigher risk of regressions as the codebase grows
Planned improvementAdd unit tests (Jest), integration tests (Supertest), and optionally E2E tests (Playwright) — see Testing & Quality

Future work roadmap

Near-term

FeatureDescription
HttpOnly cookie for refresh tokenHarden auth token storage
Automated testsUnit + integration test suite
Pagination improvementsEnsure cursor pagination is applied consistently
Error monitoringIntegrate Sentry or similar

Medium-term

FeatureDescription
Real-time notificationsSocket.IO / WebSocket connection for live notification delivery
In-app notification centerUI panel for likes, replies, new followers
Push notificationsWeb Push API or mobile push
Full-text searchSearch posts and users (MongoDB Atlas Search or Elasticsearch)

Longer-term

FeatureDescription
Precomputed timelineFan-out on write for the following feed (better scalability)
Content moderationReport / block users; automated spam detection
Media uploadsImage/video posts with CDN delivery
Global/explore feedTrending posts beyond the following graph
Multi-region deploymentLower latency for users outside the primary region
AnalyticsUsage metrics and event tracking (privacy-respecting)

Lessons learned

  • Start simple, index intentionally. Adding indexes later is easy; removing premature complexity is hard.
  • Short access token TTL matters. A 15-minute TTL dramatically limits blast radius if a token leaks — the cost (refresh overhead) is minimal.
  • Optimistic UI is important for social apps. Immediate feedback on likes/follows is a significant UX improvement over waiting for server confirmation.
  • Cursor pagination beats offset pagination early. Offset pagination produces inconsistent results when new content is inserted concurrently; cursor pagination avoids this entirely.