Fresh Data at Scale

By Syncfusion®, Inc. · Last updated

Why one fresh part slows a whole page, server islands with server:defer, fallback content, encrypted props and cookies in server islands, Cache-Control and CDN caching, live collections with defineLiveCollection(), getLiveCollection() and getLiveEntry(), and error handling.

Fresh Data at Scale

  • Some parts of a page change every second: stock left, prices, "Hello, Asha".
  • If one small part is personal or slow, the whole page must wait for it, and cannot be cached.
  • Astro has two tools for this:

    • Server islands render that one part later, on the server, while the rest of the page is fast and cacheable.
    • Live collections load fresh data on every request, with the same style as content collections.
  • In this lesson, you will also tell browsers and CDNs how long to keep a page with cache headers.

Simple lesson: keep most of the page fast and cached, and load only the fresh part on each request.

A Real-World Example

  • Asha opens a small shop page in her journal.
  • The product text is the same for everyone. It can be built once.
  • The "Only 3 left" number changes all the time.
  • She wraps the stock box in a server island. The page loads at once with "Checking stock…", then the real number appears.

Press ▶ Run. The page shows the fallback first. A moment later, the Terminal shows the island's own request, and the stock appears.

What happened:

  • The page itself is static: it was built ahead of time (▶ / in the Terminal).
  • server:defer left a placeholder with the fallback content.
  • The browser then asked the server for the island alone (/_server-islands/StockLeft).
  • The server rendered StockLeft fresh and the browser swapped it in.

What You Will Learn

In this lesson, you will learn:

  1. Why one fresh part can slow down a whole page.
  2. How to make a server island with server:defer.
  3. How to show a fallback while it loads.
  4. How props and cookies work inside server islands.
  5. How to cache pages with Cache-Control headers.
  6. How to load fresh data with live collections.
  7. How to handle live collection errors.

Server Islands

The Problem They Solve

Animation: the static page arrives at once from the cache with a grey placeholder. A second, smaller request then fills the placeholder with fresh stock data.

Page (cached, instant)

Product text

Checking stock…

Only 3 left!

Server /_server-islands/StockLeft

The page comes first. The island follows with its own small request.

  • Without islands, a personal or slow part makes the whole page on-demand.
  • On-demand pages are slower and harder to cache.
  • With a server island, the page can stay static or cached. Only the island runs on every request.
  • Server islands are not client islands. They run on the server and send no JavaScript framework. Only a tiny script fetches their HTML.

Making a Server Island

  1. Write a normal .astro component.
  2. Add server:defer where you use it: <StockLeft server:defer />.
  3. Add an adapter. Server islands are rendered on demand, so the site needs a server.
  • The page around the island can still be prerendered (static).
  • Many server islands on one page load in parallel.

Showing a Fallback

  • Put content in slot="fallback" to show it while the island loads.
  • A good fallback has the same size as the result, so the page does not jump.
  • Common fallbacks: "Loading…", a grey box, a generic avatar.

Server islands need an adapter, such as @astrojs/node, Netlify, Vercel or Cloudflare. Without one, Astro stops with an error.

Simple lesson: server:defer renders a component later, on the server, with a fallback until then.

Props and Personal Data in Server Islands

Passing Props

  • You can pass props: <StockLeft id="mug" server:defer />.
  • Astro encrypts the props and puts them in the island's URL, so visitors cannot read or change them.
  • Props must be data: text, numbers, arrays, plain objects. No functions.
  • Keep props small. Big props make the URL long (Astro switches to a POST request if it gets too long).

Press ▶ Run. Three islands share one component, each with its own id prop. They load in parallel.

  • [JS] Leave out interface Props.

Cookies and Personal Content

  • A server island gets the visitor's request, cookies included.
  • So a static, cached page can still say "Hello, Asha" in its header.
  • Inside the island, Astro.url is the island's own address. To know which page it is on, read Astro.request.headers.get("Referer").

Press ▶ Run. The home page says "Hello, guest". Click Log in as Asha. Back on the same static page, the island now greets Asha.

  • [JS] In login.js, leave out import type and : APIRoute.

Do not put personal data in a page that a CDN caches for everyone. Put it in a server island, so only the island is personal.

Simple lesson: server islands get props (encrypted) and the visitor's cookies, so cached pages can show personal parts.

Caching Pages

Cache-Control Headers

  • A cache keeps a copy of a response, so the next visitor gets it without running your code.
  • Browsers cache. CDNs (servers near your visitors) cache too.
  • An on-demand page sets how long with the Cache-Control header:
Header valueMeaning
public, max-age=60Anyone may keep it for 60 seconds
private, no-storeNever cache (personal pages)
public, s-maxage=600CDNs keep it 10 minutes, browsers follow max-age
stale-while-revalidate=30Serve the old copy while fetching a new one
  • Some hosts also read CDN-Cache-Control, a header only for the CDN.

Press ▶ Run. Open /prices and read the cache header in the Terminal.

  • [JS] Leave out : { name: string; price: number }.

Astro is also testing built-in route caching behind an experimental flag. Experimental features can change between versions. Read the Astro docs for your version before using it on a real site.

Simple lesson: Cache-Control tells browsers and CDNs how long they may keep a page.

Live Collections

Build-Time vs Live Collections

  • Content collections (Chapter 3) load data at build time. Great for posts.
  • Live collections load data on every request. Great for stock, prices, scores.
  • They live in src/live.config.ts, use defineLiveCollection(), and need an on-demand page.
Content collectionLive collection
Config filesrc/content.config.tssrc/live.config.ts
Define withdefineCollection()defineLiveCollection()
LoadedOnce, at build timeOn every request
Read withgetCollection(), getEntry()getLiveCollection(), getLiveEntry()
ErrorsStop the buildReturned as error, you handle them

A Live Loader

A live loader is an object with two functions:

  • loadCollection({ filter }) returns { entries: [...] }.
  • loadEntry({ filter }) returns one { id, data }, or nothing when it is not found.
  • Either may return { error } instead.

Press ▶ Run. Then press Refresh a few times. The sticker stock goes down, because the data is loaded fresh on every request.

  • [JS] In live.config.js, leave out interface Product and the type annotations.

Handling Errors

  • Live data can fail: the API may be down, or an id may not exist.
  • getLiveCollection() and getLiveEntry() do not throw. They return { error }.
  • Always check error before using entries or entry.

Press ▶ Run. The mug page works. Then open /products/hat: there is no hat, so the page shows a friendly message instead of crashing.

  • [JS] Leave out the ! after Astro.params.id.

Simple lesson: live collections load on every request. Always check error first.

Choosing the Right Tool

SituationBest tool
Blog posts that change when you publishContent collection, static pages
One personal or fast-changing box on a busy pageServer island
A whole page of always-fresh dataOn-demand page + live collection
A page that can be a little oldOn-demand page + Cache-Control
An interactive widget that reacts to clicksClient island (Chapter 5)

Simple lesson: static by default, a server island for one fresh part, live data for fully fresh pages.

TL;DR

  1. Problem = one fresh or personal part can make a whole page slow and uncacheable.
  2. Server island = <Comp server:defer />. Rendered on the server, after the page. Needs an adapter.
  3. Fallback = <p slot="fallback">Loading…</p> shows until the island arrives.
  4. Props = encrypted in the island URL. Data only.
  5. Cookies = server islands see the visitor's cookies. Personal parts on cached pages.
  6. Cache-Control = public, max-age=60, s-maxage=300 or private, no-store.
  7. Live collection = defineLiveCollection() in src/live.config.ts. Loaded per request.
  8. Read live data = getLiveCollection() / getLiveEntry(). Check error first.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
server:defer without an adapterIt works on a static hostIt needs a serverBuild error
No fallbackThe island appears at onceIt loads after the pageEmpty space, then a jump
A function as a server island propProps can be anythingProps are encrypted dataError
Astro.url inside the island for the page pathIt is the page URLIt is the island URLWrong path; use the Referer header
Personal data in a CDN-cached pageCaches know who is whoA cache serves one copy to allOne visitor sees another's data
Using entries without checking errorLive data never failsAPIs failThe page crashes
A live collection on a prerendered pageLive means build time tooLive is per requestStale or no data

Check Yourself

Exercises

What to Remember

  • One fresh or personal part should not slow down the whole page.
  • server:defer renders a component later on the server. Add a slot="fallback" and an adapter.
  • Server island props are encrypted. Islands see the visitor's cookies.
  • Cache-Control decides how long browsers and CDNs keep a page.
  • Live collections load data per request. Always check error.

Next: Testing and Debugging, where you check your site before visitors find the bugs.