Back to System Design
System Design
hard
mid

How would you design an e commerce frontend with rich filters and listing at scale?

Server-side filtering/search/pagination for scale; filters synced to the URL as the source of truth; product listing with cursor or page pagination; aggressive caching (React Query) per filter combination; virtualization or paginated grids; image optimization; and SSR/SSG for SEO and fast first paint.

5 min read·~15 min to think through

An e-commerce listing page at scale is about handling large catalogs with many filter combinations without shipping everything to the client.

1. Filtering & search — server-side at scale

A real catalog is too big to filter client-side. Filters become query parameters; the server returns the matching, paginated page.

  • URL is the source of truth for filters?category=shoes&size=10&sort=price&page=2. This makes filtered views shareable, bookmarkable, refresh-safe, and SEO-friendly, and the back button works.
  • Faceted filters — categories, price ranges, brands, attributes; the server also returns facet counts.
  • Debounce text search; cancel stale requests.
  • Reset to page 1 when filters change.

2. Listing & pagination

  • Pagination strategy — numbered/offset pages suit e-commerce (users expect "page 3"); cursor for infinite-scroll variants. Often a hybrid: "Load more" + page numbers.
  • CachingReact Query keyed on the full filter+page combination: revisiting a filter combo is instant; keepPreviousData avoids skeleton flicker on page change.
  • Virtualization if rendering very long grids; otherwise paginate.

3. Rendering strategy — SSR/SSG for SEO + speed

E-commerce lives on SEO and first-paint speed (conversion):

  • SSR or SSG the listing/product pages so crawlers see content and users get fast FCP/LCP.
  • Hydrate for interactivity; client-side navigation for subsequent filter changes.
  • Product detail pages often SSG + ISR (revalidate).

4. Performance

  • Image optimization — the biggest bytes: responsive srcset, WebP/AVIF, lazy-load below-the-fold, proper dimensions to avoid CLS.
  • Code splitting per route.
  • Skeletons matching the grid layout; loading/empty/error states.
  • Prefetch the next page / likely product pages on hover/idle.

5. State & architecture

  • Server state (products, facets) → React Query. UI state (filter panel open) → local.
  • URL holds filters/sort/page — derive query state from it.
  • Component structure: FilterPanel, ProductGrid, ProductCard, Pagination, SortControl.
  • Cart state in Context/store (header badge).

6. The details

  • Accessibility (filter controls, grid semantics, announce result counts).
  • Analytics on filter/sort usage.
  • Empty states ("no products match"), error recovery.
  • Optimistic add-to-cart.

The framing

"At scale, filtering and search must be server-side — the catalog is too big for the client — with filters, sort, and page living in the URL as the source of truth, so views are shareable, SEO-friendly, and back-button-correct. The listing uses offset pagination (e-commerce users expect page numbers), with React Query caching every filter+page combination and keepPreviousData to avoid flicker. I'd SSR/SSG the pages for SEO and fast first paint — conversion-critical — then optimize images hard since they're the bulk of the bytes. Server state in React Query, UI state local, URL holds the query state."

Follow-up questions

  • Why must filters live in the URL?
  • Why is server-side filtering necessary at scale?
  • Why SSR/SSG an e-commerce listing page?
  • How does React Query caching help with filter combinations?

Common mistakes

  • Client-side filtering a catalog too large to ship.
  • Filters in component state, not the URL — not shareable or refresh-safe.
  • CSR-only — bad SEO and slow first paint, hurting conversion.
  • Not optimizing images — the dominant page weight.
  • Not resetting to page 1 on filter change.

Performance considerations

  • Images dominate weight (LCP); SSR/SSG drives FCP and SEO; React Query caching cuts redundant requests; keepPreviousData and skeletons reduce perceived latency; code splitting keeps the bundle small.

Edge cases

  • Filter combination with zero results.
  • Products going out of stock / price changing between page loads.
  • Very deep pagination.
  • Slow network on mobile.
  • Deep-linked filtered URL on first load.

Real-world examples

  • Amazon/any large store: faceted filters in the URL, server-side search, SSR product pages.
  • Next.js e-commerce with SSG product pages + ISR and React Query for filtered listings.

Senior engineer discussion

Seniors put filtering on the server with the URL as source of truth, choose pagination deliberately, cache per filter combination, SSR/SSG for SEO and conversion, and prioritize image optimization — separating server and UI state cleanly.

Related questions