Static where you can, streamed where you must
If you've been living under a rock, Astro 5 already had partial hydration nailed. Plot twist: 5.5 just added Server Islands and the perf story is suddenly silly.
The Setup
Server Islands let you render a component on the server but defer it past the initial response. The fast static shell ships immediately, then the slow island streams in when it's ready. This site (aidxn.com) runs on Astro 5 — I'm already migrating two pages to 5.5 specifically for this.
---
// src/pages/index.astro
import Hero from "../components/Hero.astro";
import LiveLeads from "../components/LiveLeads.astro";
import Footer from "../components/Footer.astro";
---
<Hero />
<!-- this component hits Pipedrive — defer it -->
<LiveLeads server:defer>
<div slot="fallback" class="h-48 animate-pulse bg-white/5 rounded" />
</LiveLeads>
<Footer />The Money Pattern
The fallback slot is the magic. Ship a skeleton instantly, hydrate with real data when it lands. No client-side JS, no useEffect dance, just streaming HTML. My Rebuild Relief marketing dash went from 1.4s TTFB to 180ms on the static shell because the BigQuery card is now deferred.
---
// LiveLeads.astro — runs on every request, even with output: static
import { getLatestLeads } from "../lib/pipedrive";
const leads = await getLatestLeads(5);
---
<ul class="space-y-2">
{leads.map((l) => (
<li class="flex justify-between text-sm">
<span>{l.name}</span>
<span class="opacity-60">{l.stage}</span>
</li>
))}
</ul>The Catch
Deferred content doesn't show up in the initial HTML, so Googlebot may or may not see it depending on the crawler. Keep SEO-critical content in the static shell. Server Islands are for personalised, expensive, or freshness-sensitive bits — not your main copy.
The Verdict
This is the feature that lets a marketing site stay statically rendered while still showing live data. Same pattern Next.js does with streaming, but without the runtime overhead. If you're on Astro 5 and you haven't upgraded yet, do it tonight.