ESI (ESI)

Architecture

Edge Side Includes. A markup language for assembling pages from fragments at the CDN edge. Each fragment can have its own TTL: cache the page shell for hours but refresh the user greeting every minute. Reduces origin load for partially dynamic pages.

Updated Mar 9, 2026

Full Explanation

ESI lets you break a page into cacheable fragments. The origin returns a template with <esi:include> tags, and the CDN edge fetches and assembles the fragments before delivering the complete page to the user. Each fragment can have different cache settings.

This is perfect for pages that are 90% static but have one dynamic element (shopping cart count, user name, personalized recommendations). Without ESI, the entire page is uncacheable because of that one dynamic piece. With ESI, you cache the static shell and only fetch the dynamic fragments from origin.

ESI is supported by Varnish, Akamai, Fastly (via VCL), and some other CDNs. The spec dates back to 2001 (Akamai and Oracle co-authored it). It's not as trendy as edge compute (Workers, Lambda@Edge), but it's simpler and perfectly adequate for fragment-based assembly.

Examples

ESI template from origin:

<html>
<body>
    <!-- Cached for 1 hour -->
    <header>
        <esi:include src="/fragments/nav" />
    </header>

    <main>
        <!-- Static content, cached with page -->
        <h1>Welcome to our store</h1>
    </main>

    <aside>
        <!-- Dynamic, TTL 60s -->
        <esi:include src="/fragments/cart-count" />
    </aside>

    <!-- Fallback if fragment fails -->
    <esi:try>
        <esi:attempt>
            <esi:include src="/fragments/recommendations" />
        </esi:attempt>
        <esi:except>
            <p>Check out our popular items</p>
        </esi:except>
    </esi:try>
</body>
</html>

Varnish ESI configuration:

sub vcl_backend_response {
    # Enable ESI processing for HTML responses
    if (beresp.http.Content-Type ~ "text/html") {
        set beresp.do_esi = true;
    }
}

# Fragment endpoint with its own TTL
# /fragments/cart-count returns:
# Cache-Control: max-age=60
# <span class="cart-count">3</span>

Video Explanation

Frequently Asked Questions

Edge Side Includes. A markup language for assembling pages from fragments at the CDN edge. Each fragment can have its own TTL: cache the page shell for hours but refresh the user greeting every minute. Reduces origin load for partially dynamic pages.

ESI template from origin:

<html>
<body>
    <!-- Cached for 1 hour -->
    <header>
        <esi:include src="/fragments/nav" />
    </header>

    <main>
        <!-- Static content, cached with page -->
        <h1>Welcome to our store</h1>
    </main>

    <aside>
        <!-- Dynamic, TTL 60s -->
        <esi:include src="/fragments/cart-count" />
    </aside>

    <!-- Fallback if fragment fails -->
    <esi:try>
        <esi:attempt>
            <esi:include src="/fragments/recommendations" />
        </esi:attempt>
        <esi:except>
            <p>Check out our popular items</p>
        </esi:except>
    </esi:try>
</body>
</html>

Varnish ESI configuration:

sub vcl_backend_response {
    # Enable ESI processing for HTML responses
    if (beresp.http.Content-Type ~ "text/html") {
        set beresp.do_esi = true;
    }
}

# Fragment endpoint with its own TTL
# /fragments/cart-count returns:
# Cache-Control: max-age=60
# <span class="cart-count">3</span>

Related CDN concepts include:

  • Edge Server — A CDN server located at the network edge, close to end users. Handles caching, SSL …
  • Origin Shield — A mid-tier cache layer that sits between edge servers and the origin. Aggregates cache misses …
  • max-age — Specifies the maximum time in seconds that a response is considered fresh. Applies to all …