Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Remote Settings

The remote-settings.js module offers the ability to fetch remote settings that are kept in sync with Mozilla servers.


const { RemoteSettings } = ChromeUtils.import("resource://services-common/remote-settings.js", {});

const data = await RemoteSettings("a-key").get();

  data == [
    {label: "Yahoo",  enabled: true,  weight: 10, id: "d0782d8d", last_modified: 1522764475905},
    {label: "Google", enabled: true,  weight: 20, id: "8883955f", last_modified: 1521539068414},
    {label: "Ecosia", enabled: false, weight: 5,  id: "337c865d", last_modified: 1520527480321},

for(const entry of data) {
  // Do something with entry, e.g:
  // await InternalAPI.load(, entry.label, entry.weight);


The id and last_modified (timestamp) attributes are assigned by the server.


The list can optionally be filtered or ordered:

const subset = await RemoteSettings("a-key").get({
  filters: {
    "enabled": true,
  order: "-weight"


In order to deliver settings to subsets of the population, targets are defined for each entry (platform, language, channel, version range, …).

When the list is retrieved on the client side with RemoteSettings("key").get(), each target is evaluated and entries are filtered.


The behaviour is similar to what is done for the Normandy/SHIELD recipes.


The change event allows to be notified when the remote settings are changed. The event data attribute contains the new list of settings.

RemoteSettings("a-key").on("change", (event) => {
  const { data } = event;
  for(const entry of data) {
    // Do something with entry...


Currently, the update of remote settings is triggered by the `nsBlocklistService <>`_ (~ every 24H). But this could change to be more frequent, and even integrated within our Push service.

The create, update, and delete events work the same way. Except that the event data attribute only contains the list of entries that were created, updated, or deleted:

RemoteSettings("a-key").on("delete", async ({ data }) => {
  for(const deleted of data) {
    await InternalAPI.unload(;

File attachments

When an entry has a file attached to it, it has an attachment attribute, which contains the file related information (url, hash, size, mimetype, etc.). Remote files are not downloaded automatically.

const data = await RemoteSettings("a-key").get();

data.filter(d => d.attachment)
    .forEach(async ({ attachment: { url, filename, size } }) => {
      if (size < OS.freeDiskSpace) {
        await downloadLocally(url, filename);

Uptake Telemetry

Some :ref:`uptake telemetry <telemetry/collection/uptake>` is collected in order to monitor how remote settings are propagated.

It is submitted to a single :ref:`keyed histogram <histogram-type-keyed>` whose id is UPTAKE_REMOTE_CONTENT_RESULT_1 and the key is prefixed with main/ (eg. main/a-key with the example above).

Create new remote settings

Staff members can create new kinds of remote settings, following this documentation.

It basically consists in:

  1. Choosing a key (eg. search-providers)
  2. Assigning collaborators to editors and reviewers groups
  3. (optional) Define a JSONSchema to validate entries
  4. (optional) Allow attachments on entries

And once done:

  1. Create, modify or delete entries and let reviewers approve the changes
  2. Wait for Firefox to pick-up the changes for your settings key
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.