docs/docs/self-hosting/workspaces/configuration.mdx
Reference for the core flags, env vars, and startup checks for workspace mode. For setup and end-to-end flows, see Getting Started. For provider details and artifact routing options, see Workspace Providers.
Enable workspaces with the flag:
mlflow server \
--backend-store-uri postgresql://user:pass@localhost/mlflow \
--default-artifact-root s3://mlflow-artifacts \
--enable-workspaces
Or with env vars:
export MLFLOW_ENABLE_WORKSPACES=true
mlflow server \
--backend-store-uri ... \
--default-artifact-root ...
Disable by restarting without --enable-workspaces after moving all resources into the default workspace.
An artifact-serving-only deployment can validate and isolate artifact requests by workspace without enabling tracking APIs. The artifact server must explicitly use the same logical workspace provider as the tracking server:
mlflow server \
--artifacts-only \
--enable-workspaces \
--workspace-store-uri postgresql://user:pass@localhost/mlflow \
--artifacts-destination s3://mlflow-artifacts
MLFLOW_WORKSPACE_STORE_URI can be used instead of --workspace-store-uri. MLflow requires one of
these explicit settings in this mode because an artifact-only server has no tracking backend from
which to infer the workspace provider. The server initializes only the workspace provider; tracking,
model registry, workspace-management, and other non-artifact APIs remain disabled.
Artifact requests continue to use X-MLFLOW-WORKSPACE. The provider validates an explicit workspace
or resolves its default when the header is absent. Unknown workspaces and requests without a
resolvable default are rejected before accessing artifact storage.
To move all workspace-scoped resources into default to disable workspaces, use:
mlflow db migrate-to-default-workspace <database_uri>
By default, the command prints the rows to be moved and asks for confirmation. Use -y to skip
the prompt.
Run a dry run first to surface conflicts and see how many rows will be updated:
mlflow db migrate-to-default-workspace <database_uri> --dry-run
Use --verbose to list all conflicts instead of a truncated sample.
To selectively move resources from one workspace to another, use:
mlflow db move-resources <database_uri> \
--from <source_workspace> --to <target_workspace> \
--resource-type <table_name>
The --resource-type value is the database table name (experiments, registered_models,
evaluation_datasets, webhooks, jobs).
:::note[Gateway resources not supported]
Gateway resources (secrets, endpoints, model_definitions, budget_policies) are not
supported by this command because they have inter-table foreign-key dependencies that make moving
them independently unsafe.
:::
Filter which resources to move by name or tag:
# Move specific experiments by name
mlflow db move-resources <database_uri> \
--from default --to team-a --resource-type experiments \
--name training-v1 --name training-v2
# Move experiments matching tags (AND logic when multiple tags are given)
mlflow db move-resources <database_uri> \
--from default --to team-a --resource-type experiments \
--tag team=team-a --tag env=prod
When neither --name nor --tag is specified, all resources of the given type in the source
workspace are moved. Tag filtering is supported for experiments and registered_models only.
Use --dry-run to preview what would be moved without making changes, and -y to skip the
confirmation prompt. The command aborts if any resource name would conflict with an existing
resource in the target workspace.
mlflow.set_workspace("team-a")MLFLOW_WORKSPACE=team-aget_default_workspace() (SQL provider returns default)Clients send X-MLFLOW-WORKSPACE on REST calls; UI AJAX routes remain the same (/api, /ajax-api).
--enable-workspaces)supports_workspaces() == True unless the server is
running in --artifacts-only mode, where those stores are not initialized.--artifacts-only, the workspace provider must be configured explicitly through
--workspace-store-uri or MLFLOW_WORKSPACE_STORE_URI.default workspace exists (created by migration)--serve-artifacts, proxied artifact paths for non-default workspaces must include workspaces/<workspace>/...; legacy unprefixed paths remain valid for default.Before enabling workspaces, confirm that existing experiment artifact locations do not already
live under the reserved <default_artifact_root>/workspaces/<workspace>/... path unless
they match the workspace layout you intend to use. If they do, move or rename those artifact
roots first to avoid collisions.
<default_artifact_root>/workspaces/<workspace>/<experiment_id>; runs inherit that path.default continue to work).default_artifact_root on the workspace (via mlflow.create_workspace(...) / mlflow.update_workspace(...) or the workspace REST API). When set, MLflow uses <workspace_default_artifact_root>/<experiment_id> (no /workspaces/<workspace> prefix) for new experiments in that workspace.create_experiment() disallows artifact_location while workspaces are enabled; MLflow assigns workspace-scoped locations.GET /api/3.0/mlflow/server-info to check workspaces_enabled.404 indicates an older server without workspace support.When using workspaces with basic-auth (--app-name basic-auth), additional settings in the
auth config file (basic_auth.ini)
control workspace-level permission behavior.
| Setting | Default | Description |
|---|---|---|
grant_default_workspace_access | false | When true, all users inherit default_permission for the reserved default workspace (pre-workspaces behavior). When false, users need explicit workspace permissions even for the default workspace. |
workspace_cache_max_size | 10000 | Maximum entries in the resource-to-workspace lookup cache used for permission checks. |
workspace_cache_ttl_seconds | 3600 | TTL in seconds for cached resource-to-workspace lookups. |
grant_default_workspace_accessThis setting controls how the reserved default workspace interacts with default_permission.
false (default): The default workspace does not inherit default_permission. Users must be
granted explicit workspace permissions to access resources, even in the default workspace. This is
the most secure option for new deployments.true: The default workspace inherits default_permission for all authenticated users. The
default workspace also appears in mlflow.list_workspaces() results for every user.:::warning[Recommendation for existing instances]
If you are enabling workspaces on an existing MLflow instance that already uses basic-auth, set
grant_default_workspace_access = true for backwards compatibility. Without this, all existing
resources (which live in the default workspace) will become inaccessible to non-admin users who
lack explicit workspace permissions.
:::
Example configuration:
[mlflow]
default_permission = READ
database_uri = sqlite:///basic_auth.db
admin_username = admin
admin_password = password1234
authorization_function = mlflow.server.auth:authenticate_request_basic_auth
# Default secure setting for new deployments; for existing instances upgrading to workspaces,
# set this to true for backwards compatibility (see note above).
grant_default_workspace_access = false
workspace_cache_max_size = 10000
workspace_cache_ttl_seconds = 3600
| Variable | Description | Default |
|---|---|---|
MLFLOW_ENABLE_WORKSPACES | Enable workspace mode | false |
MLFLOW_WORKSPACE | Active workspace for client operations | None |
MLFLOW_WORKSPACE_STORE_URI | Override the workspace provider URI; falls back to the resolved tracking URI | None (falls back to resolved tracking URI) |
MLFLOW_WORKSPACE chooses the target workspace. MLFLOW_WORKSPACE_STORE_URI selects where the workspace catalog lives (and which provider to use), not which workspace; if unset, the tracking URI is reused. Providers are discovered via the mlflow.workspace_provider entry point.