On this page

Documentation

BetterConfig docs

Hosted remote config for your app. Store JSON config per environment, edit it in-app, publish to a fast edge-cached read API, and read it back over HTTPS.

Introduction

BetterConfig is hosted remote config. You keep your configuration as JSON, organized per environment, and edit it in a real in-app editor. When you publish, your config propagates to an edge-cached read API running on a global network, so your app reads fresh values with low latency from anywhere. No redeploys to change a value.

  • JSON config values, stored and versioned per environment.
  • A real in-app JSON editor with full change history and rollback.
  • Publish to a global edge read API with aggressive caching.
  • Read-only API tokens, scoped to a project or a single environment.
  • Team members with owner, editor, and viewer roles.

Also planned:Feature flags with targeting and percentage rolloutsComing soonNative typed SDKs for iOS, Android, web, Node, and GoComing soon

Today you read config over plain HTTPS with curl or fetch. See Reading your config.

Core concepts

Projects

A project is the top-level container for a single app or service. It holds your environments, config keys, tokens, and members.

Environments

Each project has multiple environments (for example dev, staging, and prod). Values are stored independently per environment.

Config keys & JSON values

A key maps to a JSON value, edited in the in-app editor. Values can be booleans, numbers, strings, or nested objects and arrays.

Versions & rollback

Every change is versioned per environment with a full audit log. You can review history and roll back to any previous version.

API read tokens

Read-only tokens created in a project's settings. A project-scoped token reads any environment; an env-scoped token is locked to one.

Members & roles

Invite teammates by email with a role: owner, editor, or viewer. Roles gate who can change config, manage tokens, and manage the team.

Quickstart

  1. 1Create a project from your dashboard.
  2. 2Add the environments you need, such as dev, staging, and prod.
  3. 3Add config keys with JSON values in the editor, then publish to push them to the edge read API.
  4. 4Open History to review every change, and roll back to a previous version if needed.
  5. 5Invite teammates by email and assign each one a role.

Import & export

Already have config somewhere else? Bring it over in one upload. Open your project's Keys page, click Import, and drop in a file. Two formats are supported, and the right one is detected automatically:

  • JSON key/value. A single JSON object where every property becomes a config key. Types are inferred from the values, including nested objects and arrays.
  • Firebase Remote Config. A Remote Config template export, downloaded from the Firebase console, CLI, or REST API. Each parameter's default value is imported with its declared type.

Example import file

config.json
{
  "checkout.enabled": true,
  "api.timeoutMs": 5000,
  "banner.title": "Spring sale",
  "theme": { "accent": "#095D43", "radius": 8 }
}

Importing from Firebase Remote Config

Export the template from Firebase first. In the console, open Remote Config, open the menu on the Parameters page, and choose Download current config file. Or grab it from the command line:

bash
# Firebase CLI
firebase remoteconfig:get -o template.json --project your-project

# Or the Remote Config REST API
curl "https://firebaseremoteconfig.googleapis.com/v1/projects/your-project/remoteConfig" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  --compressed -o template.json

Drop the downloaded file into the import dialog and the Firebase format is detected automatically. What happens to each part of the template:

  • Default values import with their declared type. BOOLEAN and NUMBER parameters are converted, JSON parameters are parsed into structured values, and everything else arrives as a string. Parameter descriptions come along too (up to 500 characters), and parameter groups are flattened into one list.
  • Conditional values are not imported. A parameter with conditional values still imports its default value, and the dialog warns you when a template carries any.
  • Some parameters are skipped, each listed with its reason in the preview: parameters that use the in-app default or have no default value, and keys outside the key grammar (1 to 120 characters, starting and ending with a letter or digit; Firebase allows leading underscores and up to 256 characters).
  • Migrating several environments? Firebase uses one project per environment, so export one template per Firebase project and import each file into the matching environment here, choosing overwrite on the later rounds.

For the full walkthrough, including what to do with conditional values, read How to migrate from Firebase Remote Config.

Nothing is written until you confirm. The dialog previews every key with its inferred type, flags the ones that already exist, and lets you pick the environment to import into. New keys receive the imported value in that environment and start from the type's default everywhere else. For keys that already exist, choose to skip them or to overwrite their value in the target environment. Overwriting appends a new version, so history stays intact and you can roll back. Re-importing an unchanged file writes nothing, and a single import handles up to 500 keys from a file of up to 10 MB. Got a bigger template? Split it into several files of up to 500 keys each and import them one at a time.

Export is the reverse. Click Exporton the Keys page to download the selected environment's live keys as a flat, alphabetically sorted JSON file. The file matches the JSON import format exactly, so you can move config between environments or projects, keep a local backup, or check a snapshot into your repo.

Reading your config

Create an API token in your project under Settings → API tokens. Tokens are read-only. A project-scoped token can read any environment in the project; an env-scoped token is locked to a single environment. Treat tokens as secrets and pass them in the Authorization header.

Request

bash
curl "https://api-public.betterconfig.dev/v1/config?project=<slug>&env=prod" \
  -H "Authorization: Bearer $BC_TOKEN"

Response

200 application/json
{
  "projectSlug": "acme-web",
  "environmentKey": "prod",
  "version": 12,
  "fetchedAt": 1730000000000,
  "values": {
    "checkout.enabled": true,
    "api.timeoutMs": 5000,
    "theme": { "accent": "#095D43" }
  }
}

Your published keys live under values. version increments on every publish and fetchedAt is the read timestamp in milliseconds.

Reading a value in JavaScript

fetch
const res = await fetch(
  "https://api-public.betterconfig.dev/v1/config?project=acme-web&env=prod",
  { headers: { Authorization: `Bearer ${process.env.BC_TOKEN}` } },
);

if (!res.ok) throw new Error(`config read failed: ${res.status}`);

const config = await res.json();
const timeout = config.values["api.timeoutMs"]; // 5000

Caching & freshness

Responses are edge-cached aggressively. Each response sends an ETag of "v<version>" and Cache-Control: public, max-age=30, stale-while-revalidate=300. Send the ETag back in If-None-Match to get a 304 Not Modified when nothing has changed, which saves bandwidth and counts against your quota less.

Errors

StatusMeaning
401Missing or invalid token.
403Token scope mismatch (the token isn't allowed to read this env).
404Project or environment not found, or nothing published yet.
429Rate limit hit, or the monthly read quota is exceeded.

Plans & limits

BetterConfig offers Free, Pro, and Ultra plans. Each plan sets limits on reads per month, stored config size, and the number of projects, environments, and members. Usage is metered and enforced, so reads past your monthly quota are rejected with a 429 until the quota resets or you upgrade. See the pricing page for the current numbers on each plan.

What's next

For worked examples of BetterConfig in real apps, see the blog. Ready to build? Create an account and publish your first config in minutes.

Stuck or have a question? Email us at support@betterconfig.dev.