Back
๐Ÿ—๏ธ

Cheatsheet โ€” System Design

Protocols ยท Machine Coding ยท Performance ยท Storage ยท Security

๐Ÿ’พ Browser Storage Options โ€” Pick the Right One

Storage Comparison

Storage Capacity Persistence Accessible from Use case
localStorage~5โ€“10 MBUntil clearedJS only (same origin)Theme, settings, tokens
sessionStorage~5 MBTab lifetimeJS only (same origin)One-time wizard state
Cookies~4 KBConfigurable expiryJS + HTTP headersAuth tokens, session IDs
IndexedDBHundreds of MBUntil clearedJS (async API)Offline data, large datasets
Cache APIGBsUntil cleared by SWJS + Service WorkerPWA asset caching
Memory (useState)RAM limitPage lifetimeCurrent component treeEphemeral UI state

Cookies โ€” Security Flags

HttpOnly Can't be read by JS โ†’ prevents XSS token theft
Secure Only sent over HTTPS
SameSite=Strict Never sent cross-site โ†’ prevents CSRF
SameSite=Lax Sent on top-level navigation GET only
SameSite=None Always sent (must also be Secure)
โœ… Auth tokens: HttpOnly + Secure + SameSite=Strict cookie (not localStorage)

IndexedDB

Transactional, async, key-value + index store. Good for offline-first apps.

// Use idb library (wrapper around verbose raw API)
import { openDB } from "idb";

const db = await openDB("mydb", 1, {
  upgrade(db) {
    db.createObjectStore("notes", { keyPath: "id" });
  },
});

await db.put("notes", { id: 1, text: "hello" });
const note = await db.get("notes", 1);
const all  = await db.getAll("notes");

State Management Patterns

Local state useState โ€” component-specific (form fields, toggles)
Shared/lifted Lift to nearest common ancestor
Context API Avoid prop drilling. Re-renders all consumers on change.
Zustand Lightweight global store. Selector-based (no unnecessary re-renders).
Redux Toolkit Predictable, devtools, good for large complex state
React Query / SWR Server state โ€” fetching, caching, sync. Don't put server data in Redux!
Rule of thumb: Local โ†’ Context โ†’ React Query (server) โ†’ Zustand/Redux (complex client)

๐Ÿ” Offline & PWA

Service Worker Caching Strategies

Cache First Serve from cache, fallback to network. Good for static assets.
Network First Try network, fallback to cache. Good for fresh content.
Stale-While-Revalidate Serve cache immediately, update cache in background. Best UX.
Cache Only Serve from cache only. Good for precached app shell.
Network Only No caching. Good for non-cacheable (analytics, forms).

Optimistic UI

Update UI immediately before server confirms. Roll back on error.

// Pattern
function addComment(text) {
  const optimistic = { id: uuid(), text, pending: true };
  setComments(prev => [...prev, optimistic]); // instant UI

  api.postComment(text)
    .then(real => setComments(prev =>
      prev.map(c => c.id === optimistic.id ? real : c)
    ))
    .catch(() => {
      setComments(prev => prev.filter(c => c.id !== optimistic.id));
      showError("Failed to post comment");
    });
}