Introduction
As Software Engineers, we often face a common challenge: deploying entire applications for minor configuration changes. Whether it's updating banner text, rolling out features to specific user segments, or running A/B experiments, the traditional approach requires a full rebuild and redeployment cycle.
Firebase Remote Config solves this problem by providing cloud-hosted configuration parameters that your application can fetch at runtime. This means you can modify app behaviour instantly without touching your deployment pipeline.
In this blog, we'll learn what Firebase Remote Config is and its use cases in a real-world application.
Firebase Remote Config
Firebase Remote Config is a cloud service that provides key-value pairs to client applications. It acts as a centralised configuration layer between your codebase and runtime behaviour.
Core capabilities:
- Feature flags: Toggle features on/off without code changes
- Targeted rollouts: Release features to specific user segments
- Dynamic content: Update UI elements based on user properties
- A/B testing: Run experiments by varying parameters across user groups
Important: Remote Config is designed for application configuration, not sensitive data. Since values are accessible on the client side, never store API keys or secrets here.
Project Setup
1. Initialize a React Project
npm create vite@latest firebase-remote-config-demo -- --template react-ts
cd firebase-remote-config-demo
npm install firebase
2. Configure Firebase SDK
Create src/firebase.ts
and add your Firebase project credentials:
import { initializeApp } from "firebase/app";
import { getRemoteConfig } from "firebase/remote-config";
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
appId: "YOUR_APP_ID",
};
export const app = initializeApp(firebaseConfig);
export const remoteConfig = getRemoteConfig(app);
// Configure fetch behaviour
remoteConfig.settings = {
fetchTimeoutMillis: 5000,
minimumFetchIntervalMillis: 30_000, // 30s for development
};
// Define fallback values
remoteConfig.defaultConfig = {
banner_enabled: false,
banner_text: "Black Friday sale is here!",
banner_bg: "#111828",
enable_new_checkout: false,
};
Configuration notes:
-
fetchTimeoutMillis
: Maximum time to wait for fetch completion -
minimumFetchIntervalMillis
: Controls fetch frequency (set to 3600000ms/1 hour in production to reduce network calls) -
defaultConfig
: Ensures app functionality even when Remote Config is unavailable
3. Create a Custom Hook
Let's build a reusable hook for accessing Remote Config values. Create src/useRemoteConfig.ts
:
import { useEffect, useState } from "react";
import { remoteConfig } from "./firebase";
import { fetchAndActivate, getValue } from "firebase/remote-config";
type RCValues = {
banner_enabled: boolean;
banner_text: string;
banner_bg: string;
enable_new_checkout: boolean;
};
export function useRemoteConfig() {
const [values, setValues] = useState<RCValues>({
banner_enabled: false,
banner_text: "๐ Welcome to our shop!",
banner_bg: "#111827",
enable_new_checkout: false,
});
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchAndActivate(remoteConfig)
.then(() => {
setValues({
banner_enabled: getValue(remoteConfig, "banner_enabled").asBoolean(),
banner_text: getValue(remoteConfig, "banner_text").asString(),
banner_bg: getValue(remoteConfig, "banner_bg").asString(),
enable_new_checkout: getValue(remoteConfig, "enable_new_checkout").asBoolean(),
});
})
.catch((error) => {
console.error("Remote Config fetch failed:", error);
// Defaults remain in place on error
})
.finally(() => setLoading(false));
}, []);
return { values, loading };
}
How it works:
-
fetchAndActivate
: Fetches the latest config and applies it immediately - Type safety ensures correct value types at compile time
- Error handling prevents app crashes if Firebase is unreachable
- Loading state prevents UI flicker during initial fetch
4. Implement Components
Dynamic Banner Component (src/components/FestivalBanner.tsx
):
import React from "react";
import { useRemoteConfig } from "../useRemoteConfig";
export function FestivalBanner() {
const { values, loading } = useRemoteConfig();
if (loading || !values.banner_enabled) return null;
return (
<div
style={{
background: values.banner_bg,
color: "#fff",
padding: "12px",
borderRadius: "8px",
textAlign: "center",
marginBottom: "20px",
}}
>
<strong>{values.banner_text}</strong>
</div>
);
}
Feature-Flagged Checkout (src/components/CheckoutButton.tsx
):
import React from "react";
import { useRemoteConfig } from "../useRemoteConfig";
export function CheckoutButton() {
const { values } = useRemoteConfig();
const handleCheckout = () => {
if (values.enable_new_checkout) {
alert("๐ New Checkout Flow Activated!");
// Route to new checkout implementation
} else {
alert("Classic Checkout");
// Route to legacy checkout
}
};
return (
<button
onClick={handleCheckout}
style={{
padding: "12px 24px",
borderRadius: "8px",
background: values.enable_new_checkout ? "#10b981" : "#3b82f6",
color: "white",
border: "none",
cursor: "pointer",
fontSize: "16px",
}}
>
{values.enable_new_checkout ? "๐ Try New Checkout" : "Checkout"}
</button>
);
}
5. Integrate in Main App
Update src/App.tsx
:
import React from "react";
import { FestivalBanner } from "./components/FestivalBanner";
import { CheckoutButton } from "./components/CheckoutButton";
function App() {
return (
<div style={{
maxWidth: "680px",
margin: "40px auto",
padding: "0 20px",
fontFamily: "system-ui, sans-serif"
}}>
<h1>T-Mate</h1>
<FestivalBanner />
<div style={{ marginTop: "20px" }}>
<CheckoutButton />
</div>
</div>
);
}
export default App;
Firebase Console Configuration
Setting Up Parameters
- Navigate to Firebase Console โ Remote Config
- Add the following parameters:
-
banner_enabled
(Boolean) โ Default:false
-
banner_text
(String) โ Default:"๐ Welcome to our shop!"
-
banner_bg
(String) โ Default:"#111827"
-
enable_new_checkout
(Boolean) โ Default:false
-
Creating Conditions
Geographic targeting:
- Condition name: "Users in India"
- Rule:
country == 'in'
- Override:
banner_enabled = true
,banner_text = "๐ช Diwali Sale is Live!"
Percentage rollout:
- Condition name: "10% Beta Users"
- Rule: User in random percentile <= 10%
- Override:
enable_new_checkout = true
Publishing Changes
After configuring parameters and conditions, click "Publish changes." Updates propagate to clients within the configured minimumFetchIntervalMillis
window.
Testing the Implementation
npm run dev
Open your browser and test:
- The banner appears/disappears based on your location
- Refresh multiple times to see the new checkout (10% probability) potentially
- Modify values in Firebase Console and observe changes after the fetch interval
Production Best Practices
1. Implement Defensive Defaults
Always provide fallback values in multiple layers:
- In
remoteConfig.defaultConfig
- In your hook's initial state
- In component logic where appropriate
This ensures your app remains functional even when Remote Config is unavailable due to network issues or service outages.
2. Optimize Fetch Intervals
Development environment: 30 seconds (fast iteration)
Production environment: 1-2 hours (reduced network overhead)
remoteConfig.settings = {
fetchTimeoutMillis: 5000,
minimumFetchIntervalMillis:
process.env.NODE_ENV === 'production' ? 3600000 : 30000,
};
3. Never Store Sensitive Data
Remote Config values are accessible through browser DevTools. Use it for:
- โ Feature flags
- โ UI configurations
- โ Content variations
- โ API keys
- โ Authentication tokens
- โ Private credentials
4. Version Your Parameters
Consider including version information in parameter names for complex rollouts:
feature_checkout_v2_enabled: boolean
feature_checkout_v3_enabled: boolean
This allows you to manage multiple versions simultaneously during transitions.
5. Monitor and Measure
Integrate with Firebase Analytics to track the impact of configuration changes:
import { logEvent } from "firebase/analytics";
// Track which checkout version users see
logEvent(analytics, 'checkout_version_shown', {
version: values.enable_new_checkout ? 'v2' : 'v1'
});
6. Implement Gradual Rollouts
Start with small percentages and gradually increase:
- Day 1: 1% of users
- Day 3: 5% of users
- Day 7: 25% of users
- Day 14: 100% of users
Monitor error rates and user metrics at each stage before proceeding.
Advanced Use Cases
User Segmentation
Combine multiple conditions for precise targeting:
- Show premium features only to paid subscribers
- Display region-specific content based on locale
- Enable beta features for users with specific app versions
A/B Testing Integration
Firebase Remote Config integrates seamlessly with Firebase A/B Testing, allowing you to:
- Test multiple parameter variations
- Measure conversion rates
- Automatically roll out winning variants
Dynamic Theming
Store theme configurations remotely:
theme_primary_color: "#3b82f6"
theme_secondary_color: "#10b981"
theme_mode: "light" | "dark"
Conclusion
Firebase Remote Config provides a robust solution for decoupling application configuration from deployment cycles. By implementing feature flags, targeted rollouts, and dynamic content delivery, you gain the flexibility to respond quickly to business requirements without the overhead of continuous redeployment.
Start with simple use cases like dynamic banners and feature toggles, then expand to more sophisticated implementations as your confidence grows. If you like this blog and want to learn more about Frontend Development and Software Engineering, you can follow me on Dev.to.
Top comments (0)