Use Remote Config in server environments

Firebase Remote Config supports server-side configuration using the Firebase Admin SDKs for Node.js (v12.1.0+), Python (v6.7.0+), Java (v9.7.0+), and Go (v4.17.0+).

This capability lets you dynamically manage the behavior and configuration of server-side applications using Remote Config. This includes serverless implementations like Cloud Functions for Firebase and containerized services on Cloud Run.

Unlike Firebase client SDKs, which fetch a client-specific configuration derived from the Remote Config template, the server-side Remote Config SDK downloads or fetches a complete Remote Config template from Firebase. Your server can then evaluate the template with each incoming request and use its own logic to serve a customized response with very low latency. You can use conditions to control and customize responses based on random percentages and client attributes defined in custom signals.

With server-side Remote Config, you can:

  • Define configuration parameters for applications running on or accessed through your server, allowing for use cases like remotely configuring AI model parameters and prompts and other integrations, to ensure your API keys stay secure.
  • Dynamically adjust parameters in response to changes in your environment or other application changes, like updating LLM parameters and model endpoints.
  • Control costs by remotely updating the APIs your server calls.
  • Generate custom configurations on-the-fly for clients that access your server.
  • Record which clients received a parameter value and use this in Cloud Functions for Firebase as part of an entitlement verification system.

You can deploy server-side Remote Config on Cloud Run, Cloud Functions for Firebase, or self-hosted server environments.

Before you begin

Follow the instructions in Add the Firebase Admin SDK to your server to create a Firebase project, set up a service account, and add the Firebase Admin SDK to your server. Make sure you use a supported version of the Admin SDK for your platform:

  • Node.js: Firebase Admin Node.js SDK v12.1.0+
  • Python: Firebase Admin Python SDK v6.7.0+
  • Java: Firebase Admin Java SDK v9.7.0+
  • Go: Firebase Admin Go SDK v4.17.0+

Step 1: Initialize the Firebase Admin SDK and authorize API requests

When you initialize the Admin SDK with no parameters, the SDK uses Google Application Default Credentials and reads options from the GOOGLE_APPLICATION_CREDENTIALS environment variable. Initialize the SDK and configure Remote Config for your platform:

Node.js

Import initializeApp and getRemoteConfig, then initialize your Firebase application instance:

import { initializeApp } from "firebase-admin/app";
import { getRemoteConfig } from "firebase-admin/remote-config";

// Initialize Firebase
const firebaseApp = initializeApp();

Python

Import firebase_admin (along with asyncio and json for asynchronous template loading and JSON parsing), then initialize the application:

import firebase_admin
import asyncio
import json

firebase_admin.initialize_app()

Java

Initialize the Firebase Admin SDK using FirebaseOptions and your service account credentials:

// Initialize the Firebase Admin SDK
FirebaseOptions options = new FirebaseOptions.Builder()
    .setCredentials(GoogleCredentials.fromStream(serviceAccount))
    .build();
FirebaseApp.initializeApp(options);

Go

Initialize the Firebase application and create a RemoteConfig client instance:

ctx := context.Background()

// Initialize Firebase
app, err := firebase.NewApp(ctx, nil)
if err != nil {
    log.Fatalln("Error initializing app:", err)
}

remoteConfig, err := app.RemoteConfig(ctx)
if err != nil {
    log.Fatalln("Error initializing remote config client:", err)
}

Step 2: Identify default parameter values for your server application

Identify the variables in your app that you want to dynamically update with Remote Config. Then, consider which variables must be set by default in your application and what their default values should be. This ensures that your application runs successfully even if its connection to the Remote Config backend server is interrupted.

For example, if you are writing a server application that manages a generative AI function, you might set a default model name, prompt preamble, and a generative AI configuration, like the following:

Parameter name Description Type Default value
model_name Model API name String gemini-2.0-flash
preamble_prompt Prompt to prepend to the user's query String I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!
generation_config Parameters to send to the model JSON {"stopSequences": ["I hope this helps"], "temperature": 0.7, "maxOutputTokens": 512, "topP": 0.1, "topK": 20}

Step 3: Configure your server application

After you've determined the parameters you want to use with Remote Config, configure your application to set default values, fetch the server-specific Remote Config template, and evaluate its values.

  1. Access and load the Remote Config server template.

    Node.js

    Initialize the server template using initServerTemplate() and call load() to fetch the template from the backend:

    // Initialize server-side Remote Config
    const rc = getRemoteConfig(firebaseApp);
    const template = rc.initServerTemplate();
    
    // Load Remote Config
    await template.load();
    

    If you're using Node.js within Cloud Functions for Firebase, you can use the asynchronous getServerTemplate() function to initialize and load the template in a single step:

    // Initialize server-side Remote Config
    const rc = getRemoteConfig(firebaseApp);
    const template = await rc.getServerTemplate();
    

    Python

    Initialize the server template using init_server_template() and call load() to fetch the template from the backend:

    from firebase_admin import remote_config
    
    # Initialize server-side Remote Config
    template = remote_config.init_server_template()
    
    # Load the template from the backend
    asyncio.run(template.load())
    

    Alternatively, if you're using Python with Cloud Functions for Firebase, you can use the asynchronous get_server_template() function to initialize and load the template in a single step:

    # Initialize server-side Remote Config
    template = await remote_config.get_server_template()
    

    Java

    Initialize the server-side Remote Config client using FirebaseRemoteConfig.getInstance():

    // Initialize server-side Remote Config client
    FirebaseRemoteConfig rc = FirebaseRemoteConfig.getInstance();
    

    Alternatively, if you're using Java with Cloud Functions for Firebase, you can use getServerTemplate() to initialize and load the template in a single step:

    ServerTemplate template = rc.getServerTemplate();
    

    Go

    Initialize the server template using InitServerTemplate() and call Load() to fetch the template from the backend:

    // Initialize server-side Remote Config
    defaultConfig := make(map[string]any)
    templateDataJSON := ""
    template, err := remoteConfig.InitServerTemplate(defaultConfig, templateDataJSON)
    if err != nil {
        log.Fatalln("Error initializing server template:", err)
    }
    
    // Load Remote Config
    err = template.Load(ctx)
    if err != nil {
        log.Fatalln("Error fetching server template:", err)
    }
    

    Another way you can initialize the template is by using the GetServerTemplate function to retrieve the required server template. You can convert this template to a JSON format that can be stored locally, and subsequently initialize this JSON template using the InitServerTemplate function.

  2. To ensure that your application runs successfully even if its connection to the Remote Config backend server is interrupted, add default values for each parameter in your app.

    Node.js

    Add a defaultConfig object inside your initServerTemplate or getServerTemplate template function:

    const template = rc.initServerTemplate({
      defaultConfig: {
        model_name: "gemini-pro",
        generation_config: '{"stopSequences": [], "temperature": 0.7, "maxOutputTokens": 512, "topP": 0.1, "topK": 20}',
        preamble_prompt: "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
      },
    });
    
    // Load Remote Config
    await template.load();
    

    Python

    Add a default_config dictionary inside your init_server_template or get_server_template template function:

    template = remote_config.init_server_template({
      'default_config': {
        'model_name': "gemini-pro",
        'generation_config': '{"stopSequences": [], "temperature": 0.7, "maxOutputTokens": 512, "topP": 0.1, "topK": 20}',
        'preamble_prompt': "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
      },
    })
    
    # Load Remote Config
    asyncio.run(template.load())
    

    Another way you can initialize a template is by using the get_server_template function to retrieve the required server template. You can convert this template to a JSON format using the template.to_json function. This JSON template can be stored locally, and you can subsequently initialize this JSON template using the init_server_template function.

    Java

    Add a defaultConfig object using KeysAndValues inside your getServerTemplate function:

    // Initialize default config using KeysAndValues
    KeysAndValues defaultConfig = new KeysAndValues.Builder()
                                      .put("rc_param_1", "default value 1")
                                      .put("rc_param_2", "default value 2")
                                      .build();
    ServerTemplate template = rc.getServerTemplate(defaultConfig);
    

    Alternatively, you can pass a default cached template while initializing Remote Config, which can be used even when the connection to the Remote Config server is interrupted:

    String templateDataJSON = "{}"; // add your default template as JSON
    ServerTemplate template = rc.serverTemplateBuilder()
                        .defaultConfig(defaultConfig)
                        .cachedTemplate(templateDataJSON)
                        .build();
    

    Go

    Add a defaultConfig map inside your InitServerTemplate or GetServerTemplate template function:

    // Initialize server-side Remote Config
    defaultConfig := make(map[string]any)
    defaultConfig["model_name"] = "gemini-2.0-flash"
    
    // Assume the type generationConfig has been defined
    defaultConfig["generation_config"] = &generationConfig{
        StopSequences:   []string{"I hope this helps"},
        Temperature:     0.7,
        MaxOutputTokens: 512,
        TopP:            0.9,
        TopK:            30,
    }
    
    defaultConfig["preamble_prompt"] = "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
    
    templateDataJSON := ""
    template, err := remoteConfig.InitServerTemplate(defaultConfig, templateDataJSON)
    if err != nil {
        log.Fatalln("Error initializing server template:", err)
    }
    
    // Load Remote Config
    err = template.Load(ctx)
    if err != nil {
        log.Fatalln("Error fetching server template:", err)
    }
    
  3. After the template loads, evaluate the template to import parameters and values from the template:

    Node.js

    Use template.evaluate():

    // Add template parameters to config
    const config = template.evaluate();
    

    Python

    Use template.evaluate():

    # Add template parameters to config
    config = template.evaluate()
    

    Java

    Use template.evaluate():

    // Add template parameters to config
    ServerConfig config = template.evaluate();
    

    Go

    Use template.Evaluate() with an empty evaluation context when no conditions are applied:

    // An empty evaluation context means no conditions are applied.
    evaluationContext := make(map[string]any)
    config, err := template.Evaluate(evaluationContext)
    if err != nil {
        log.Fatalln("Error evaluating template:", err)
    }
    
  4. Optionally, if you set conditions in your Remote Config template, define and provide the context values you want:

    • If using percentage conditions, add the randomization ID (randomizationId, randomization_id, or randomizationID) that you want to use to evaluate your conditions within the template evaluation function.
    • If using custom signals, define the attributes and their values. Custom signals are available with Firebase Admin Node.js SDK v12.5.0+, Python SDK v6.7.0+, Java SDK v9.7.0+, and Go SDK v4.17.0+.

    For example, you might set a Firebase installation ID or user ID as the randomization ID to ensure that each user that contacts your server is added to the proper randomized group, version as a custom signal to target specific client versions, and platform as a custom signal to target client platforms.

    For more information about conditions, see Condition rule types.

    Node.js

    Pass an evaluation context object containing randomizationId and any custom signals to template.evaluate():

    // Add template parameters to `config`. Evaluates the
    // template and returns the parameter value assigned to
    // the group assigned to the {randomizationId} and version.
    const config = template.evaluate({
      randomizationId: "2ac93c28-c459-4760-963d-a3974ec26c04",
      version: "1.0",
      platform: "Android"
    });
    

    Python

    Pass a dictionary containing randomization_id and any custom signals to template.evaluate():

    # Add template parameters to `config`. Evaluates the
    # template and returns the parameter value assigned to
    # the group assigned to the {randomization_id} and version.
    config = template.evaluate({
      'randomization_id': "2ac93c28-c459-4760-963d-a3974ec26c04",
      'version': "1.0",
      'platform': "Android"
    })
    

    Java

    Create a KeysAndValues context containing randomizationId and any custom signals, and pass it to template.evaluate():

    // Add custom signals and randomizationId
    KeysAndValues context = new KeysAndValues.Builder()
                                    .put("custom_signal_key", "99")
                                    .put("randomizationId", "2ac93c28")
                                    .build();
    
    // Evaluate the template with signals
    ServerConfig config = template.evaluate(context);
    

    Go

    Pass an evaluation context map containing randomizationID and any custom signals to template.Evaluate():

    // Add template parameters to `config`. Evaluates the
    // template and returns the parameter value assigned to
    // the group assigned to the {randomizationID}, version, and platform.
    evaluationContext := make(map[string]any)
    evaluationContext["randomizationID"] = "2ac93c28-c459-4760-963d-a3974ec26c04"
    evaluationContext["version"] = "1.0"
    evaluationContext["platform"] = "Android"
    
    config, err := template.Evaluate(evaluationContext)
    if err != nil {
        log.Fatalln("Error evaluating template:", err)
    }
    
  5. Next, extract the parameter values you need from the evaluated configuration object. Use getter methods to cast values from Remote Config into the expected format.

    For example, if you're implementing Agent Platform on your server and want to change the model and model parameters, you might configure parameters for model_name and generation_config. Here are the supported getter methods and an example of how to access Remote Config values for each platform:

    Node.js

    Supported getter methods:

    • Boolean: getBoolean
    • Object: getValue
    • Number: getNumber
    • String: getString

    // Replace defaults with values from Remote Config.
    const generationConfig =
      JSON.parse(
        config.getString('generation_config'));
    
    const is_ai_enabled = config.getBoolean('is_ai_enabled');
    
    const model = config.getString('model_name');
    
    // Generates a prompt comprised of the Remote Config
    // parameter and prepends it to the user prompt
    const prompt = `${config.getString('preamble_prompt')} ${req.query.prompt}`;
    

    Python

    Supported getter methods:

    • Boolean: get_bool
    • Integer: get_int
    • Float: get_float
    • String: get_string
    • Value source: get_value_source

    # Replace defaults with values from Remote Config.
    generation_config = json.loads(config.get_string('generation_config'))
    is_ai_enabled = config.get_bool('is_ai_enabled')
    model = config.get_string('model_name')
    
    # Generates a prompt comprised of the Remote Config
    # parameter and prepends it to the user prompt.
    prompt = f"{config.get_string('preamble_prompt')}{req.args.get('prompt')}"
    

    Java

    Supported getter methods:

    • Boolean: getBoolean
    • String: getString
    • Double: getDouble
    • Long: getLong
    • Value source: getValueSource

    // Get the model name
    String modelName = config.getString("model_name");
    // Get the origin of value assigned to param
    ValueSource modelNameSource = config.getValueSource("model_name");
    

    The method getValueSource returns a ValueSource that indicates whether the parameter's value source is STATIC, REMOTE, or DEFAULT.

    Go

    Supported getter methods:

    • Boolean: GetBoolean
    • Integer: GetInt
    • Float: GetFloat
    • String: GetString
    • Value source: GetValueSource

    // Replace defaults with values from Remote Config.
    
    // Assume the type generationConfig has been defined
    var genConfig generationConfig
    err = json.Unmarshal([]byte(config.GetString("generation_config")), &genConfig)
    if err != nil {
        log.Fatalln("Error unmarshaling generation config:", err)
    }
    model := config.GetString("model_name")
    
    // Parameter created on the console
    isAIEnabled := config.GetBoolean("is_ai_enabled")
    
    // Generates a prompt comprised of the Remote Config
    // parameter and prepends it to the user prompt (assume it is extracted from the request body)
    userPrompt := "What is Remote Config?"
    prompt := fmt.Sprintf("%s %s", config.GetString("preamble_prompt"), userPrompt)
    
  6. If your server is long-running, as opposed to a serverless environment, periodically reload the template (for example, using setInterval in Node.js or java.util.Timer in Java) to confirm that you're fetching the most up-to-date template from the Remote Config server.

Step 4: Set server-specific parameter values in Remote Config

Next, create a server Remote Config template and configure parameters and values to use in your app.

Here's how to create a server-specific Remote Config template:

  1. In the Firebase console, go to the DevOps & Engagement > Remote Config > Parameters page.

  2. From the Client/Server selector at the top of the page, select Server.

  3. Define Remote Config parameters with the same names and data types as the parameters that you defined in your app and provide values. These values will override the default configuration (defaultConfig or default_config) you set in Configure your server application when you fetch and evaluate the template and assign these values to your variables.

  4. Optionally, set conditions to persistently apply values to a random sample of instances or custom signals you define. For more information about conditions, see Condition rule types.

  5. When you've finished adding parameters, click Publish changes.

  6. Review the changes and click Publish changes again.

Step 5: Deploy with Cloud Functions for Firebase or Cloud Run

If your server application is lightweight and event-driven, you should consider deploying your code using Cloud Functions for Firebase. For example, say you have an app that includes character dialogue powered by a generative AI API (for example, Google AI or Agent Platform). In this case, you could host your LLM-serving logic in a function that your app calls on-demand.

If you're building a server-rendered web app, App Hosting has support for popular web frameworks.

Otherwise, you might consider Cloud Run. To deploy your server app with Cloud Run, follow the quickstart guide for your language:

For more information about the best use cases for Cloud Run and Cloud Functions for Firebase, see Cloud Functions for Firebase vs. Cloud Run: when to use one over the other.

Next steps