# Streaming SSR for Search Results Page
The search results page is server-rendered using React Suspense streaming (Next.js App Router). The HTML shell is sent immediately; pin data is embedded inline in the stream and handed off to the client store during hydration โ no second network fetch. Subsequent interactions (infinite scroll, filter changes) are handled client-side.
Blocking SSR was rejected because it adds Elasticsearch's response time directly to TTFB. Pure CSR was rejected because first paint shows an empty grid, harming LCP and making search result URLs non-crawlable. Streaming SSR eliminates the TTFB penalty while preserving SEO and shareability. This pattern is validated by Pinterest's own production implementation.
# CDC for Elasticsearch Sync
Elasticsearch is populated via Change Data Capture (WAL tailing on Postgres โ queue โ indexing consumer), not by dual-writing from the API. The API writes only to PostgreSQL; Elasticsearch is a derived view.
Dual write was rejected because a partial failure (Postgres succeeds, ES fails or vice versa) creates an inconsistency with no clean recovery path. Polling was rejected because it introduces unbounded query cost as pin volume grows and provides no replay mechanism after ES downtime. CDC makes the data flow unidirectional and recoverable โ if ES goes down, events queue up and replay automatically when it recovers.