Serve Dynamic Content with Cloud Functions

Firebase Hosting allows you to use Cloud Functions to perform server-side processing. This means that you can support dynamic generation of content for your Firebase Hosting site. Here are some examples of what this allows you to do:

  • Serve dynamic content. Instead of only serving static content, you can perform server-side logic through a function to return a dynamically generated response. For example, you can have a URL like /blog/<id-for-blog-post>. This URL pattern can be pointed to a function that dynamically uses the URL blog post ID parameter to retrieve content dynamically from your Firebase Realtime Database.
  • Prerender your single page apps to improve SEO. This allows you to create dynamic meta tags for sharing across various social networks.
  • Keep your web app lightweight. You can create an API through Cloud Functions for your Firebase Hosting site to asynchronously retrieve content. This allows you to reduce initial load times for your web app by keeping the client code lightweight and loading content asynchronously through a function.

Note that Firebase Hosting is subject to a 60‑second request timeout. For dynamic content that might take longer than 60 seconds to generate, consider using the App Engine flexible environment.

Connect Cloud Functions to Firebase Hosting

To connect a function to Firebase Hosting, you'll need to set up Cloud Functions, write your function, create rewrite rules, and deploy your changes. To improve the performance of your dynamic content, you can optionally tune your cache settings.

Set up Cloud Functions for Firebase Hosting

If you've already set up Cloud Functions for Firebase you can skip this step and proceed to create an HTTP function. This will set up Cloud Functions for your Firebase project.

First make sure you have the latest version of the Firebase CLI, which requires Node.js v6.3.1 or greater. You can install Node.js by following the instructions on Installing Node.js will also install npm.

To check which version of Node.js that you have installed, run the following command in your terminal:

node --version

To install the latest version of the Firebase CLI, run the following command in your terminal:

npm install -g firebase-tools

To connect your local machine to your Firebase account and obtain access to your Firebase projects, run the following command:

$ firebase login

Next, you'll need to initialize functions. If you have not initialized your Hosting project, run the following command in your terminal. When prompted, choose to initialize Hosting and Cloud Functions within your project directory.

firebase init

If you have an existing project with Hosting, run the following command within your project directory to only initialize Cloud Functions.

firebase init functions

Create an HTTP function to your Hosting site

Open /functions/index.js in your favorite editor, then replace its contents with the following code. This will create a simple HTTP function named bigben.

const functions = require('firebase-functions');

exports.bigben = functions.https.onRequest((req, res) => {
  const hours = (new Date().getHours() % 12) + 1 // London is UTC + 1hr;
  res.status(200).send(`<!doctype html>
      ${'BONG '.repeat(hours)}

Direct Hosting requests to your function

With rewrite rules you can direct requests that match specific patterns to a single destination. For example, to direct all requests from the page /bigben on your Hosting site to execute the bigben function, open firebase.json, then add the following rewrite configuration under the hosting section.

  "hosting": {
    "public": "public",

    // Add the following rewrites section *within* "hosting"
    "rewrites": [ {
      "source": "/bigben", "function": "bigben"
    } ]


Note that Firebase Hosting is subject to a 60‑second request timeout. So even if you configure your HTTP function with a longer request timeout, you'll still receive an HTTP status code 504 (request timeout) if your function requires more than 60 seconds to run. To support this kind of dynamic content, consider using the App Engine flexible environment.

You can learn more about rewrite rules here.

Run dynamic content locally

You can deploy and run your dynamic content locally using the Firebase CLI. This allows you to test your site before deploying to production.

To use this feature, firebase-tools must be v3.8.0 or greater, and firebase-functions SDK must be v0.5.7 or greater. To update both, run the following commands in the functions/ directory for your project:

npm install --save firebase-functions@latest
npm install -g firebase-tools

To run dynamic content locally, use firebase serve:

firebase serve --only hosting,functions # emulates local hosting code and local functions code
firebase serve --only hosting # emulates local hosting code, but uses production functions as proxies

This command outputs a URL where you can view or test your Firebase Hosting content and HTTP functions.


After creating a function and setting your rewrite rules, you'll need to deploy your Firebase project. Run the following command in your terminal.

firebase deploy

After deployment, you'll notice that your function is normally accessible through a URL like the following:


All traffic on your Firebase Hosting site that matches the path specified in the rewrite rules will be proxied to the appropriate function.

Try out the sample

After everything is deployed, you can go to /bigben on your Firebase Hosting site to see it in action.


Using cookies

When using Firebase Hosting together with Cloud Functions, cookies are generally stripped from incoming requests. This is necessary to allow for efficient CDN cache behavior. Only the specially-named __session cookie is permitted to pass through to the function execution.

When present, the __session cookie is automatically made a part of the cache key, meaning that it is impossible for two users with different cookies to receive the other's cached response. You should only use the __session cookie if your function serves different content depending on user authorization.

Manage cache behavior

Firebase Hosting uses a powerful global CDN (content delivery network) to make your site as fast as possible. Static content on Firebase Hosting is cached until a new version is deployed. Because functions generate content dynamically, requests that are handled by a function do not cache in the CDN by default. You can configure caching behavior yourself to speed up your app and reduce function execution costs.

Set Cache-Control

The main tool that you'll use to manage cache is the Cache-Control header. By setting it, you can communicate both to the browser and the CDN how long your content should be cached. In your function, you set Cache-Control like so:

res.set('Cache-Control', 'public, max-age=300, s-maxage=600');

The above header does three things:

  • Marks the cache as public. This means that this content is okay to be cached by intermediate servers (in our case, the CDN). By default, Cache-Control is set to private which means that only the user's browser is allowed to cache it.
  • Tells the browser for how many seconds it can cache the content with max-age. In the above example, we're telling the browser to cache for five minutes.
  • Tells the CDN for how many seconds it can cache the content with s-maxage. In the above example, we're telling the CDN to cache for ten minutes.

When setting max age, you should set it to the largest amount of time with which you're comfortable having users receive stale content. If a page changes every few seconds, this will be a small number. Other content, however, can safely be cached for hours, days, or even months.

You can learn more about the Cache-Control header on the Mozilla Developer Network.

When is cached content served?

If you have set a public Cache-Control header, your content will be cached in the CDN based on:

  • The hostname
  • The path
  • The query string
  • The content of the headers specified in Vary

The Vary header is how to signal which parts of the request are important in determining your response. Most of the time, you don't need to worry about this. Firebase Hosting will automatically ensure that an appropriate Vary header is set on your response for common situations. This includes making sure that any session cookie or authorization header that you're using is made part of the cache key, preventing accidental leaks of content.

In some advanced use cases, you may have other headers that you need to affect the cache. When that's the case, you can simply set the Vary header on your response:

res.set('Vary', 'Accept-Encoding, X-My-Custom-Header');

With these settings, two otherwise identical requests with different X-My-Custom-Header headers are cached separately.

Send feedback about...

Need help? Visit our support page.