On-demand Builders

This feature is in early access BETA.

On-demand Builders are serverless functions used to generate web content as needed that’s automatically cached on Netlify’s Edge CDN. They enable you to build pages for your site when a user visits them for the first time and then cache them at the edge for subsequent visits.

Key characteristics of On-demand Builders:

  • They accept GET requests only.
  • They don’t provide access to HTTP headers or query parameters from incoming requests.
  • Response caching is based on the URL path and can’t be customized.
  • A new site deploy invalidates the cache associated with builders in the same deploy context, such as the same Deploy Preview number or the same branch deploy.

On-demand Builders are the first step towards our goal to make Distributed Persistent Rendering possible on Netlify. The current implementation has the following constraints:

  • The cached response from a builder is local to the edge node that served the request. A request to any other edge node re-triggers the builder and can result in a different response.
  • Because the response doesn’t persist globally, it may drop from the cache after a period of time, requiring the builder to execute again on a later request to the same node.

We welcome your feedback on this early access feature. You can join the conversation about On-demand Builders in our Support Forums.

# Create On-demand Builders

To get started, follow our docs to create a Netlify Function in JavaScript or in TypeScript. Use the synchronous function format, and return a response that can be served as a cached static asset. For example, you could return a full HTML page or a processed image file. To convert the function to a builder, use the builder() method from the @netlify/functions package.

First, add the package to your site dependencies:

npm install -D @netlify/functions

Then, pass your function as a parameter to the builder() method and export this method as the handler from your serverless function file.

const { builder } = require("@netlify/functions")

async function myfunction(event, context) {
    // logic to generate the required content
}

exports.handler = builder(myfunction);

Here’s a basic example:

const { builder } = require("@netlify/functions")

async function handler(event, context) {

  return {
    statusCode: 200,
    headers: {
      "Content-Type": "text/html",
    },
    body: `
    <!DOCTYPE html>
	    <html>
		    <body>
		      Hello World
		    </body>
    </html>
    `,
  };
}

exports.handler = builder(handler);

On success, the builder returns a 200 status code and an HTML page with a “Hello World” message.

# Use On-demand Builders

Similar to Netlify Functions, On-demand Builders can be called at endpoints relative to the base URL of your site: /.netlify/functions/FUNCTION_NAME.

Builder endpoints can be called directly like regular web URLs or can be executed by redirecting traffic from another URL.

For example, consider a news site with a large amount of infrequently visited, archived content. You can use a builder to generate those less-frequented pages on-demand when a user requests them. The request URL might be something like this:

https://myawesomenews.com/.netlify/functions/my-archive-builder/article/199x-news

The first call to the builder invokes it and returns the generated page, assuming that’s the logic in your function. Subsequent calls return the cached page content until the next builder execution.

In another example, if you want to replace a static image src with a custom-sized image generated using a builder, you can format an img tag like this:

<img alt="kittens." src="/.netlify/functions/my-image-transformer/file/kittens.jpg/width/640">

The first builder call processes and returns the image, and subsequent calls return the cached image until the next builder execution.

# Customize paths with redirects

In the example above, you might prefer to use a different URL instead of the default builder endpoint. You can do this by redirecting traffic from a URL to the builder using redirect rules in the _redirects file or netlify.toml Netlify configuration file.

Here are some examples with _redirects file and netlify.toml syntax.

    /images/*  /.netlify/functions/my-image-transformer   200!
    
    /archive   /.netlify/functions/my-archive-builder  200
    
    [[redirects]]
      from = "/images/*"
      to = "/.netlify/functions/my-image-transformer"
      status = 200
      force = true
    
    [[redirects]]
      from = "/archive"
      to = "/.netlify/functions/my-archive-builder"
      status = 200
    

    The original path is passed to the builder as part of the event object. To continue an example from above, a call to /images/kittens.jpg/width/640 triggers the my-image-transformer function with the following values passed to it as part of the event:

    { 
    	"path": "/images/kittens.jpg/width/640",
    	"httpMethod": "GET"
    	...
    }
    

    For more information about the event parameter and the Netlify Functions programming model, refer to our docs on synchronous function format.

    # Redirect workaround for query parameters

    On-demand Builders currently don’t process or cache query parameters from redirected paths. In most cases, it’s best to embed these parameters into the path directly, but in cases where you don’t control the path, you can re-shape it with an additional redirect rule to the path resolution. The first rule must have a 3XX HTTP status code, as that ensures a new URL for our redirects engine to process the second rule, passing your new path to the builder. Here’s an example in _redirects syntax:

    /generated/image url=:url w=:w /img/:url/:w 301! 
    
    /img/:url/:w /.netlify/functions/image 200
    

    # Shadowing

    Redirect rules leverage shadowing, which means that they trigger only if there isn’t already an asset at the specified from path. This can be useful if your prebuilt assets and content generated by your builder share the same path.

    If you prefer to trigger the proxy regardless of the presence of a pre-built asset, you can append ! to the status code in the _redirects file, or add force = true in netlify.toml.

    # Frequently asked questions

    # How can I opt in to use On-demand Builders during the early access period?

    There’s no sign-up needed. To participate, set up a builder as explained above and deploy it as part of your site assets.

    # How do I secure On-demand Builders? Can I apply role-based access?

    You can use the same authentication and authorization strategy as the rest of your Netlify site. We recommend using JSON Web Tokens (JWT), roles, and redirect rules for managing granular access. Refer to our docs on role-based access control to learn more.

    # Can I set the TTL / cache duration?

    No, you can’t set time to live (TTL) or cache duration. The cache lifecycle is fully managed by Netlify.

    # Is there a maximum payload size that can be cached?

    Because Netlify Functions are powered by AWS Lambda, there’s a hard limit of 6 MB for the builder response payload.

    # Can I develop and test locally?

    You can build and test the logic like any other serverless function using Netlify Dev. When testing locally, however, caching isn’t available.

    # Does On-demand Builders execution count towards Netlify Functions usage or build minutes?

    Requests to builders that return a previously non-cached response count towards your Netlify Functions usage for billing purposes. This includes requests per month and run time per month. If a cached response is available and served, no function invocation is made and no usage is incurred against your Netlify Functions allotment.

    On-demand Builders execution doesn’t count towards build minutes.