v150 · html · shipped
Out of order streaming
A new declarative HTML mechanism for delivering page sections out of document order — using processing-instruction markers and <template for> — so servers can stream expensive content at the end of the response and have it appear in the right place, without any JavaScript. Ships in Chrome 150 on desktop and Android.
at a glance
| Shipped in | Chrome 150 (desktop, Android); DevTrial from Chrome 148 |
|---|---|
| Status | Enabled by default |
| Flag | None (was chrome://flags/#enable-experimental-web-platform-features) |
| Standards position | Gecko: positive · WebKit: under consideration |
| Spec | WHATWG HTML spec pull #11818 |
| Explainer | WICG / declarative-partial-updates — patching-explainer.md |
| ChromeStatus | 5111042975465472 — Out of order streaming |
why it exists
Server-side rendering works best when HTML is streamed top-to-bottom: the browser can paint the top of the page while the server is still computing the bottom. But some page sections are expensive — a user's personalised feed, live prices, or a complex query result — while surrounding structure is cheap. With traditional streaming you must choose between blocking the early paint on expensive content or sending a skeleton that JavaScript fills in later.
Out of order streaming lets the server send a placeholder marker in the cheap HTML that arrives early, then send the expensive section as a patch at the end of the response stream. The browser moves the patch to the correct position in the document as the bytes arrive — no client-side JavaScript needed.
Source: WICG declarative-partial-updates explainer.the two primitives
1. Marker processing instructions — the placeholder
A processing instruction of the form <?marker id> (or paired <?start id> / <?end id>) reserves a named slot in the document where patched content will be inserted. These markers have no visual rendering; they are annotation nodes only.
<!-- Early in the response: fast static HTML -->
<header>...</header>
<main>
<h1>Latest prices</h1>
<?marker prices> <!-- placeholder for slow content -->
<p>Loading…</p>
</main>
<footer>...</footer>
<!-- Later in the response: expensive content finally ready -->
<template for="prices">
<table>...live prices...</table>
</template>
2. <template for> — the patch
A <template> element with a for attribute names the target marker. When the browser parses the template it moves its content to the position of the named marker, replacing the placeholder. No JavaScript event listener, no innerHTML manipulation.
<!-- Inserts children at the <?marker content> position -->
<template for="content">
<article>
<h2>Expensive article</h2>
<p>...</p>
</article>
</template>
range markers (paired start/end)
For replacing a block of existing content rather than a single insertion point, use paired markers:
<?start skeleton>
<p class="skeleton">Loading…</p>
<?end skeleton>
<!-- Replaces everything between the start and end markers -->
<template for="skeleton">
<p>Real content is here.</p>
</template>
Source: declarative-partial-updates explainer, §Patching.
end-to-end example (server perspective)
<!-- Server begins streaming immediately with fast, cheap HTML -->
<!doctype html>
<html><body>
<nav>...</nav>
<main>
<?marker user-feed>
<p>Loading your feed…</p>
</main>
<aside>...</aside>
<!-- Server finishes the expensive DB query 300ms later,
then flushes the patch at the bottom of the same response -->
<template for="user-feed">
<article>Post 1</article>
<article>Post 2</article>
</template>
</body></html>
The user sees the nav and sidebar immediately. The feed replaces the "Loading…" placeholder when the template arrives, with no layout thrash and no JavaScript. This is the server-rendered equivalent of Suspense (React) or progressive hydration, without a client framework.
browser support
| Chrome / Edge | 150 (enabled by default) |
|---|---|
| Firefox | Standards-positive; not yet shipped |
| Safari | Under consideration |