Settings

Settings are how administrators configure an iTwin.js application for end-users. A setting is a named value — a string, number, boolean, object, or array — that controls application behavior at run-time. Settings can live at different levels of persistence — in-memory app defaults, cloud-backed iTwin settings, or iModel-specific overrides — and the runtime resolves them by priority so higher-priority values win.

New to this topic? Start with the Workspaces and Settings overview to understand how Settings, settings containers, and WorkspaceDb relate before diving in here.

What is a setting?

A setting controls application behavior. For example, an application might provide a check box to toggle "dark mode"; whether users can see that check box in the first place could be controlled by a setting. Each individual's dark mode choice is a user preference, not a setting.

A Setting is a name-value pair. The value can be:

  • A string, number, or boolean;
  • An object containing properties of any of these types; or
  • An array containing elements of one of these types.

A SettingName must be unique, 1 to 1024 characters long with no leading nor trailing whitespace, and should begin with the schema prefix of the schema that defines it. For example, LandscapePro might define:

"landscapePro/ui/defaultToolId" "landscapePro/ui/availableTools" "landscapePro/flora/preferredStyle" "landscapePro/flora/treeDbs" "landscapePro/hardinessRange"

Forward slashes create logical groupings, similar to file paths.

Settings schemas

The metadata describing a group of related Settings is defined in a SettingGroupSchema. The schema is based on JSON Schema, with the following additions:

  • schemaPrefix (required) — a unique name for the schema. All names in the schema inherit this prefix.
  • description (required) — a description appropriate for displaying to a user.
  • settingDefs — an object of SettingSchemas describing individual settings, indexed by name.
  • typeDefs — an object of SettingSchemas describing reusable types that can be referenced by other schemas.
  • order — an optional integer used to sort schemas in a user interface.

We can define the LandscapePro schema programmatically as follows:

const schema: SettingGroupSchema = { schemaPrefix: "landscapePro", description: "LandscapePro configuration settings", settingDefs: { "flora/preferredStyle": { type: "string", description: "The name of one of a set of predefined 'styles' of foliage that might be used to select appropriate flora", }, "flora/treeDbs": { type: "array", extends: "itwin/core/workspace/workspaceDbList", }, "ui/defaultTool": { type: "string", description: "Id of the tool that is active when the application starts", }, "ui/availableTools": { type: "array", description: "Ids of tools that should be shown to the user", items: { type: "string", }, combineArray: true, }, "hardinessRange": { type: "object", description: "Specifies the upper and lower limits on the hardiness zone for flora that can survive in a region", properties: { minimum: { type: "integer", extends: "landscapePro/hardinessZone", description: "The lower limit on hardiness zone for flora that can survive in a region", }, maximum: { type: "integer", extends: "landscapePro/hardinessZone", description: "The upper limit on hardiness zone for flora that can survive in a region", }, }, }, }, typeDefs: { hardinessZone: { type: "integer", description: "A USDA hardiness zone used to describe the surivability of plants in a geographical region", minimum: 0, maximum: 13, }, }, };

This schema defines 5 settingDefs and 1 typeDef. The "landscapePro" prefix is implicitly included in each name — for example, the full name of "hardinessRange" is "landscapePro/hardinessRange".

The "hardinessZone" typeDef represents a USDA hardiness zone as an integer between 0 and 13. The "hardinessRange" settingDef reuses it for both "minimum" and "maximum" via extends. Note that extends requires the schema prefix, even within the same schema.

The "flora/treeDbs" settingDef extends "workspaceDbList" from the workspace schema, with prefix "itwin/core/workspace".

Registering schemas

The set of currently-registered schemas can be accessed via IModelHost.settingsSchemas. Register new ones using SettingsSchemas.addFile, SettingsSchemas.addDirectory, or — for programmatic schemas — SettingsSchemas.addGroup:

IModelHost.settingsSchemas.addGroup(schema);

Register schemas shortly after invoking IModelHost.startup, using the IModelHost.onAfterStartup event:

IModelHost.onAfterStartup.addListener(() => { IModelHost.settingsSchemas.addGroup(landscapeProSchema); });

For brevity, some of the extract snippets later in this article call IModelHost.settingsSchemas.addGroup(...) directly. In an application, register schemas during startup, usually in IModelHost.onAfterStartup.

All schemas are unregistered when IModelHost.shutdown is invoked.

Schema validation behavior

Validation occurs lazily when you retrieve a setting value — not when the value is stored. When you call methods like Settings.getString, Settings.getObject, or Settings.getBoolean, the value is validated against the registered schema for that setting name:

  • If no schema is registered for the setting name, the value passes through unchecked.
  • If a schema is registered, type mismatches throw an error — for example, if the schema declares a setting to be a string but the dictionary supplies a number.
  • For object types, required fields are enforced and extends references are resolved recursively.

Because validation happens on retrieval, register your schemas early — ideally via IModelHost.onAfterStartup — so that type errors are caught as soon as the setting is first accessed.

Settings dictionaries

A SettingsDictionary supplies values for one or more Settings. The Settings for the current session can be accessed via the settings property of IModelHost.appWorkspace.

Dictionary structure tips: Prefix all setting names with the schemaPrefix of the schema that defines them to avoid collisions. Use forward-slash grouping (e.g., "landscapePro/ui/", "landscapePro/flora/") to organize related settings — prefer flat keys over deeply nested objects. Keep individual dictionary files focused on a single concern so administrators can override only what they need at a particular SettingsPriority.

Let's load a settings dictionary that provides values for some of the LandscapePro settings:

const values: SettingsContainer = { "landscapePro/ui/defaultTool": "place-shrub", "landscapePro/ui/availableTools": ["place-shrub", "place-koi-pond", "apply-mulch"], }; const props: SettingsDictionaryProps = { // A unique name for this dictionary. name: "LandscapeProDefaults", // This dictionary's priority relative to other dictionaries. priority: SettingsPriority.defaults, }; IModelHost.appWorkspace.settings.addDictionary(props, values);

Now access the values via IModelHost.appWorkspace.settings:

let defaultTool = IModelHost.appWorkspace.settings.getString("landscapePro/ui/defaultTool"); // "place-shrub" let availableTools = IModelHost.appWorkspace.settings.getArray<string>("landscapePro/ui/availableTools"); // ["place-shrub", "place-koi-pond", "apply-mulch"] let preferredStyle = IModelHost.appWorkspace.settings.getString("landscapePro/flora/preferredStyle"); // undefined const preferredStyleOrDefault = IModelHost.appWorkspace.settings.getString("landscapePro/flora/preferredStyle", "default"); // "default"

Note that getString returns undefined for "landscapePro/preferredStyle" because our dictionary didn't provide a value for it. The overloads of that function (and similar functions like Settings.getBoolean and Settings.getObject) allow specifying a default value.

Note: In general, avoid caching setting values — just query them each time you need them, because they can change at any time. If you must cache (for example, when populating a user interface), listen for the Settings.onSettingsChanged event.

Any number of dictionaries can be added to Workspace.settings. Let's add another:

IModelHost.appWorkspace.settings.addDictionary({ name: "LandscapeProOverrides", priority: SettingsPriority.application, }, { "landscapePro/flora/preferredStyle": "coniferous", "landscapePro/ui/defaultTool": "place-koi-pond", "landscapePro/ui/availableTools": ["place-gazebo", "apply-mulch"], });

This dictionary adds a value for "landscapePro/flora/preferredStyle", and defines new values for two settings already defined in the previous dictionary. When we look up those settings again:

defaultTool = IModelHost.appWorkspace.settings.getString("landscapePro/ui/defaultTool"); // "place-koi-pond" availableTools = IModelHost.appWorkspace.settings.getArray<string>("landscapePro/ui/availableTools"); // ["place-gazebo", "apply-mulch", "place-shrub", "place-koi-pond"] preferredStyle = IModelHost.appWorkspace.settings.getString("landscapePro/flora/preferredStyle"); // "coniferous"

"landscapePro/flora/preferredStyle" is no longer undefined. The value of "landscapePro/ui/defaultTool" has been overwritten. And "landscapePro/ui/availableTools" contains the merged contents of both dictionaries — because the settingDef has SettingSchema.combineArray set to true.

Settings priorities

Configurations are often layered. SettingsPriority defines which dictionaries take precedence — the highest-priority dictionary that provides a value for a given setting name wins.

Specific values:

A SettingsDictionary of application priority or lower resides in IModelHost.appWorkspace. iTwin-scoped settings are loaded into the workspace returned by IModelHost.getITwinWorkspace — see iTwin settings. Settings of even higher priority (branch and iModel) are stored in an IModelDb.workspace — see iModel settings.

In practice, an organization admin can set org-wide defaults at organization priority. An iTwin-level admin can selectively override settings for their iTwin at iTwin priority without affecting other iTwins. For example, to add a dictionary at iTwin priority:

const iTwin555: SettingsContainer = {}; iTwin555["itwin/core/default-tool"] = "measure"; iTwin555["app5/markerName"] = "arrows"; iTwin555["app5/markerIcon"] = "arrows.ico"; workspace = iModel.workspace; settings = workspace.settings; settings.addDictionary({ name: "for iTwin 555", priority: SettingsPriority.iTwin }, iTwin555); defaultTool = settings.getString("itwin/core/default-tool"); // returns "measure"

When that iTwin's settings are no longer needed, drop the dictionary:

workspace = iModel.workspace; settings = workspace.settings; settings.dropDictionary({ name: "for iTwin 555" }); defaultTool = settings.getString("itwin/core/default-tool"); // returns "select" again

Note: The examples above use Settings.addDictionary, which loads dictionaries into memory for the current session only — they are not persisted to any container or iModel. For cloud-backed iTwin and organization settings — where dictionaries are fetched from settings containers on demand — see Settings containers below.

What about "landscapePro/ui/availableTools"? In the LandscapePro schema, the corresponding settingDef has SettingSchema.combineArray set to true, meaning that when multiple dictionaries provide a value for the setting, they are merged into a single array, eliminating duplicates, and sorted in descending order by dictionary priority.

How settings are stored

The sections below cover three progressively richer ways to work with settings:

  • Session-only (in-memory): Settings.addDictionary loads a dictionary for the current session. Good for testing, app defaults, and short-lived overrides.
  • iTwin persisted: IModelHost.saveSettingDictionary writes named dictionaries to the iTwin's cloud-hosted settings container. Changes persist across sessions and are shared with other users.
  • iModel persisted: EditTxn.saveSettingDictionary writes named dictionaries directly into the iModel.
  • Settings container (cloud-managed storage): A settings container stores settings as key-value pairs in a dedicated cloud container with its own versioning and access control — see Settings containers.

iTwin settings

Each iTwin has its own workspace with its own Settings that can override and/or supplement the application workspace's settings. In the default iTwin-settings workflow, these settings are stored as named SettingsDictionarys in a single auto-discoverable cloud container tagged with containerType: "settings", in its default settings-db WorkspaceDb, scoped to that iTwin. Whenever IModelHost.getITwinWorkspace is called, all named dictionaries in that container are loaded into the returned Workspace.settings at SettingsPriority.iTwin. An application working in the context of a particular iTwin should resolve setting values by asking IModelHost.getITwinWorkspace, which will fall back to IModelHost.appWorkspace if the iTwin's setting dictionaries don't provide a value for the requested setting.

Before using iTwin settings, ensure two services are configured:

With those in place, load the iTwin workspace scope:

const iTwinWorkspace = await IModelHost.getITwinWorkspace(iTwinId); const defaultView = iTwinWorkspace.settings.getString("myApp/defaultView"); iTwinWorkspace.close();

The returned Workspace gives you access to all settings and resources associated with the iTwin.

Important: The workspace returned by IModelHost.getITwinWorkspace is caller-owned. Call close() on it when you are finished to release cloud connections and cached data.

IModelHost.getITwinWorkspace is discovery-only. If no settings container exists yet, it returns an empty workspace. The first default settings container is created on first write via IModelHost.saveSettingDictionary.

Saving iTwin settings

To save a named settings dictionary for an iTwin, call IModelHost.saveSettingDictionary with a dictionary name and a SettingsContainer of key-value pairs:

IModelHost.settingsSchemas.addGroup({ schemaPrefix: "myApp", description: "MyApp settings", settingDefs: { defaultView: { type: "string" }, maxDisplayedItems: { type: "integer" }, }, }); await IModelHost.saveSettingDictionary(iTwinId, "myApp/settings", { "myApp/defaultView": "plan", "myApp/maxDisplayedItems": 100, });

If no settings container exists for the specified iTwin yet, IModelHost.saveSettingDictionary creates the default one automatically on first write. The dictionary name becomes the resource name in that container. Multiple named dictionaries can coexist in the same container.

This write path is typically used by setup/admin code. Ordinary read-only clients usually just call IModelHost.getITwinWorkspace.

Deleting iTwin settings

To remove an entire named dictionary, use IModelHost.deleteSettingDictionary:

await IModelHost.deleteSettingDictionary(iTwinId, "myApp/settings");

Reading iTwin settings

To read iTwin settings, query the settings of the Workspace returned by IModelHost.getITwinWorkspace:

const workspace = await IModelHost.getITwinWorkspace(iTwinId); const defaultViewFromRead = workspace.settings.getString("myApp/defaultView"); const maxItems = workspace.settings.getNumber("myApp/maxDisplayedItems"); workspace.close();

iTwin settings are loaded with SettingsPriority.iTwin priority.

iModel settings

Note: Storing settings directly in an iModel (via EditTxn.saveSettingDictionary) ties configuration to a single iModel file. Settings cannot be discovered without opening the iModel and cannot be versioned independently. For new projects, consider storing shared settings in a cloud-hosted settings container instead — it is discoverable by iTwinId, versioned independently, and does not require an iModel to be open.

Migrating older code? Deprecated IModelDb.saveSettingDictionary and IModelDb.deleteSettingDictionary map to EditTxn.saveSettingDictionary and EditTxn.deleteSettingDictionary, typically via withEditTxn.

Each IModelDb has its own Workspace, accessible via IModelDb.workspace. This workspace inherits app-level settings (via IModelHost.appWorkspace) and layers on settings stored inside the iModel itself. iTwin-level settings are not loaded automatically — see Referencing iTwin settings from an iModel for how to include them. Because iModel-level dictionaries are loaded at SettingsPriority.iModel — the highest built-in priority — they override any lower-priority setting with the same name.

Use iModel settings when a particular iModel needs configuration that differs from the rest of its iTwin, or when you want to persist metadata (like an iTwin settings container reference) inside the iModel so it is available in future sessions.

Saving iModel settings

To save settings into an iModel, call EditTxn.saveSettingDictionary (via withEditTxn) with a dictionary name and a SettingsContainer of key-value pairs:

interface HardinessRange { minimum: number; maximum: number; } const range: HardinessRange = { minimum: 6, maximum: 8 }; await iModel.acquireSchemaLock(); await withEditTxn(iModel, async (txn) => txn.saveSettingDictionary("landscapePro/iModelSettings", { "landscapePro/hardinessRange": range, }));

The dictionary name (e.g. "landscapePro/iModelSettings") identifies the dictionary within the iModel. If a dictionary with that name already exists, it is replaced; otherwise a new one is created. You can save multiple dictionaries under different names.

Note that modifying iModel settings requires an exclusive write lock on the entire iModel (obtained automatically by withEditTxn) — ordinary users should never do this.

Deleting iModel settings

To remove an entire settings dictionary from an iModel, use EditTxn.deleteSettingDictionary (via withEditTxn):

await withEditTxn(iModel, async (txn) => txn.deleteSettingDictionary("landscapePro/iModelSettings"));

Reading iModel settings

Settings saved into the iModel are automatically loaded into IModelDb.workspace. Read them the same way you read any other settings — the priority stack resolves the effective value:

const hardinessRange = iModel.workspace.settings.getObject<HardinessRange>("landscapePro/hardinessRange"); // returns { minimum: 6, maximum: 8 } defaultTool = iModel.workspace.settings.getString("landscapePro/ui/defaultTool"); // returns "place-koi-pond" as specified by IModelHost.appWorkspace.settings.

In the example above, landscapePro/hardinessRange was saved into the iModel, so it is returned from the iModel's dictionary. But landscapePro/ui/defaultTool was not saved at the iModel level, so it falls through to the app-level dictionary that defined it earlier.

Overriding iTwin settings per iModel

Because SettingsPriority.iModel is higher than SettingsPriority.iTwin, any setting saved at the iModel level takes precedence over the same setting at the iTwin level.

For example, suppose the iTwin setting landscapePro/flora/preferredStyle is "naturalistic" for the entire iTwin, but one particular iModel represents a formal garden:

// The iTwin setting says "naturalistic", but this iModel is a formal garden. await withEditTxn(iModel, async (txn) => txn.saveSettingDictionary("landscapePro/iModelOverrides", { "landscapePro/flora/preferredStyle": "formal", }));

Now when the application reads landscapePro/flora/preferredStyle from this iModel's workspace scope, it gets "formal". All other iModels in the iTwin continue to use the iTwin-level value.

Referencing iTwin settings from an iModel

An iModel doesn't inherently know which iTwin settings container it should use. By saving the container's identity as an iModel-level setting, the iTwin settings become part of the iModel's workspace — so IModelDb.workspace becomes the single place to resolve all settings and resources the iModel uses.

// Save a floating reference — no `version` field means the iModel // always loads the latest available version of the iTwin settings. const iTwinWorkspaceForModelRef = await IModelHost.getITwinWorkspace(iTwinId); const settingsSourcesForModelRef = iTwinWorkspaceForModelRef.settingsSources; assert(undefined !== settingsSourcesForModelRef); await withEditTxn(iModel, async (txn) => txn.saveSettingDictionary("landscapePro/iModelSettings", { "landscapePro/itwinSettingsRef": settingsSourcesForModelRef, })); iTwinWorkspaceForModelRef.close();

The next time the iModel is opened, your application reads the saved reference and passes it to the IModelHost.getITwinWorkspace overload that accepts WorkspaceDbSettingsProps:

const settingsRef = iModel.workspace.settings.getSetting<WorkspaceDbSettingsProps>("landscapePro/itwinSettingsRef"); if (settingsRef !== undefined) { const iTwinWs = await IModelHost.getITwinWorkspace(settingsRef); // iTwinWs.settings now contains the iTwin-level settings. // ... use the settings, then close when finished: iTwinWs.close(); }

By default this resolves to the latest version of those settings.

Pinning iTwin settings versions

If you need to pin the iModel to a specific version of the iTwin settings — so that its configuration does not change even when the iTwin settings are updated — save the version alongside the container props:

// Pin the iModel to the exact settings version currently in use. // Unlike the floating reference above, adding a `version` field locks // the iModel to a specific snapshot — configuration won't change when // the iTwin's settings are updated later. const iTwinWorkspaceToPin = await IModelHost.getITwinWorkspace(iTwinId); const floatingRefs = iTwinWorkspaceToPin.settingsSources; assert(undefined !== floatingRefs); // Add an explicit version to each settings source reference. const sources = Array.isArray(floatingRefs) ? floatingRefs : [floatingRefs]; const pinnedRefs = sources.map((source) => ({ ...source, version: "1.0.0" })); await withEditTxn(iModel, async (txn) => txn.saveSettingDictionary("landscapePro/iModelSettings", { "landscapePro/itwinSettingsRef": pinnedRefs, })); iTwinWorkspaceToPin.close();

Settings containers

A settings container is a cloud container tagged with containerType: "settings" that stores settings in its default settings-db WorkspaceDb. It stores settings as a flat JSON object — SettingName keys mapped to Setting values. The default auto-discovered iTwin-settings workflow assumes one settings container per iTwin; IModelHost.getITwinWorkspace can discover that single container by iTwinId without needing an iModel open.

graph LR
    SDB["Settings container
(cloud)"] Dict["SettingsDictionary
(in-memory)"] Stack["Settings priority stack
(iTwin workspace,
appWorkspace, or
IModelDb.workspace)"] SDB -->|"loadSettingsDictionary() → JSON"| Dict Dict -->|"Settings.addJson()\nat specified priority"| Stack

This is what distinguishes a settings container from a workspace container: a settings container is where you start. You load settings from a settings container, and those settings tell your application which workspace containers hold the binary resources it needs.

How settings containers fit the priority system

When a settings container is loaded into the runtime via Workspace.loadSettingsDictionary, its contents become one SettingsDictionary in the Settings priority stack. The priority is explicitly specified by the caller via WorkspaceDbSettingsProps.priority — it is not automatically derived from the container's scope.

Advanced: managing settings containers

Most applications do not need to manage settings containers directly — IModelHost.getITwinWorkspace handles discovery only, and the default iTwin settings container is created on first write via IModelHost.saveSettingDictionary. The workflows below are for administrators who need fine-grained control: discovering containers, creating them explicitly, versioning, or updating individual settings.

Discovering settings containers

You can find settings containers by using WorkspaceEditor.queryContainers:

// Query the BlobContainer service for settings containers associated with an iTwin. const containerMetadata = await WorkspaceEditor.queryContainers({ iTwinId, containerType: "settings" }); // Each entry includes a containerId and label that can be displayed in an admin UI. for (const entry of containerMetadata) { console.log(`Container: ${entry.containerId}, label: ${entry.label}`); // eslint-disable-line no-console }

This is useful when building an admin UI that lets users inspect or choose settings containers explicitly, without hardcoding container IDs.

If multiple settings containers exist for the same iTwin, these admin APIs can still return them — but the default convenience APIs (IModelHost.getITwinWorkspace and IModelHost.saveSettingDictionary) cannot automatically choose among them.

To open matching containers for editing in a single call, use WorkspaceEditor.findContainers. It queries the service, requests write tokens, and opens each matching container:

// Find and open settings containers for a given iTwin in a single call. // This queries the BlobContainer service for settings containers matching the iTwinId, // requests write access tokens, and opens each matching container. const settingsEditor = WorkspaceEditor.construct(); const settingsContainers = await settingsEditor.findContainers({ iTwinId, containerType: "settings" }); expect(settingsContainers).to.not.be.undefined;

Creating a settings container and writing settings

The example below creates a new cloud container, writes some initial settings, and publishes them:

// Advanced/admin workflow: // create a settings container explicitly and manage it by container identity. // Do not create an additional `containerType: "settings"` container for an iTwin // that already relies on `IModelHost.saveSettingDictionary` + // `IModelHost.getITwinWorkspace(iTwinId)`, because those convenience APIs // auto-select only a single settings container per iTwin. const editor = WorkspaceEditor.construct(); const container: EditableWorkspaceContainer = await editor.createNewCloudContainer({ metadata: { label: "Project Settings", description: "Settings for this iTwin" }, scope: { iTwinId }, containerType: "settings", manifest: { workspaceName: "settings", description: "iTwin settings container" }, }); // Write settings using withEditableDb — it acquires the lock, opens the db, // runs your callback, then closes the db and publishes. const settings: SettingsContainer = { "myApp/theme": "dark", "myApp/maxItems": 50, }; await container.withEditableDb("admin", (settingsDb) => { settingsDb.updateSettingsResource(settings); }); editor.close();

This is an advanced admin workflow. Only use it when you intend to manage settings containers by explicit container identity. If an iTwin already relies on the default IModelHost.saveSettingDictionary + IModelHost.getITwinWorkspace flow, creating an additional containerType: "settings" container for the same iTwin will disable automatic container selection for both convenience APIs.

The key steps are:

  1. Create an editor — call WorkspaceEditor.construct. The caller is responsible for calling close() when finished.
  2. Create a containerWorkspaceEditor.createNewCloudContainer with containerType: "settings" (this must be specified explicitly; the default is "workspace").
  3. Acquire the write lockEditableWorkspaceContainer.acquireWriteLock. Only one user can hold the lock at a time.
  4. Open an EditableWorkspaceDbEditableWorkspaceContainer.getEditableDb returns an EditableWorkspaceDb.
  5. Write settings — use EditableWorkspaceDb.updateSettingsResource to replace all settings in the resource.
  6. Release the lockEditableWorkspaceContainer.releaseWriteLock publishes your changes. Alternatively, EditableWorkspaceContainer.abandonChanges discards them.

Important: Always release the write lock when you are done. Failing to release it will prevent other administrators from modifying the container until the lock expires.

Updating individual settings

Often you need to change a single setting without touching the rest. EditableWorkspaceDb.updateSettingsResource reads the existing settings, updates the specified entry, and writes the result back — other settings are preserved:

// Update a single setting without affecting others. // Re-open the container, acquire the write lock, read existing settings, change one entry, and publish. const updateEditor = WorkspaceEditor.construct(); const updateContainers = await updateEditor.findContainers({ iTwinId, containerType: "settings" }); const updateContainer = updateContainers[0]; await updateContainer.withEditableDb("admin", (db) => { const current = JSON.parse(db.getString("settingsDictionary") ?? "{}") as SettingsContainer; current["myApp/maxItems"] = 100; db.updateSettingsResource(current); }); updateEditor.close();

To remove a setting entirely, use EditableWorkspaceDb.removeString.

To inspect all settings in a container, use WorkspaceDb.getString:

// Read all settings stored in a settings container. let allSettings: SettingsContainer = {}; const readEditor = WorkspaceEditor.construct(); const readContainers = await readEditor.findContainers({ iTwinId, containerType: "settings" }); const readContainer = readContainers[0]; await readContainer.withEditableDb("admin", (readDb) => { const raw = readDb.getString("settingsDictionary"); allSettings = raw ? JSON.parse(raw) as SettingsContainer : {}; }); readEditor.close();

Versioning

Like all WorkspaceDbs, each settings container uses semantic versioning. Once a version is published to cloud storage it becomes immutable. To evolve settings, create a new version via EditableWorkspaceContainer.createNewWorkspaceDbVersion, make changes, and release the write lock. The versioning workflow is the same as described in creating workspace resources.

Last Updated: 28 April, 2026