{
  "schema_version": 2,
  "id": "develop/ai/featureform/register-providers",
  "title": "Register providers",
  "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/",
  "summary": "Register storage, compute, catalog, and secret providers in a Redis Feature Form workspace.",
  "aliases": [
    "/develop/ai/featureform/streaming/"
  ],
  "tags": [],
  "last_updated": "2026-09-11T15:54:40+01:00",
  "children": [
    {
      "id": "develop/ai/featureform/register-providers/databricks",
      "summary": "Register Databricks compute, Unity Catalog, and secret providers with Redis Feature Form.",
      "title": "Register Databricks providers",
      "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/databricks/"
    },
    {
      "id": "develop/ai/featureform/register-providers/snowflake",
      "summary": "Register Snowflake storage and compute with Redis Feature Form.",
      "title": "Register a Snowflake provider",
      "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/snowflake/"
    },
    {
      "id": "develop/ai/featureform/register-providers/postgresql",
      "summary": "Register PostgreSQL storage and compute with Redis Feature Form.",
      "title": "Register a PostgreSQL provider",
      "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/postgresql/"
    },
    {
      "id": "develop/ai/featureform/register-providers/s3",
      "summary": "Register Amazon S3 and S3-compatible object storage with Redis Feature Form.",
      "title": "Register an S3 provider",
      "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/s3/"
    },
    {
      "id": "develop/ai/featureform/register-providers/redis",
      "summary": "Register standalone Redis and Redis Cluster online-store providers with Redis Feature Form.",
      "title": "Register Redis providers",
      "url": "https://redis.io/docs/latest/develop/ai/featureform/register-providers/redis/"
    }
  ],
  "page_type": "content",
  "content_hash": "ffd99c2d8137c02755f2da345c385329976dcbd32a00dbfdb91f451a1851cb89",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Register the providers and secret backends Redis Feature Form needs before you author features or transformations. Providers connect a workspace to external systems, and definitions files reference them by name."
    },
    {
      "id": "prerequisites",
      "title": "Prerequisites",
      "role": "content",
      "text": "Before you register a provider, make sure you have:\n\n- A [workspace](https://redis.io/docs/latest/develop/ai/featureform/manage-workspace).\n- The [`redis-featureform` Python package](https://redis.io/docs/latest/develop/ai/featureform/quickstart#install-the-ff-cli) installed. It includes the Python client and the `ff` command-line interface (CLI).\n- Network access from the Feature Form server and its workers to the external system.\n- A registered secret provider for each credential reference in the provider configuration.\n\nThe examples show Python first and the equivalent `ff` command second. [Configure authentication](https://redis.io/docs/latest/operate/featureform/configure-auth) through an active profile or environment variables before you use either interface. `ff.Client.from_env()` reads that configuration, including `FEATUREFORM_BASE_URL` and `FEATUREFORM_TOKEN` when set. The CLI connects to `localhost:9090` by default; use `--server <host:port>` or configure another endpoint when the server is elsewhere.\n\nThe Python examples on this page use these workspace-scoped clients:\n\n[code example]\n\nProvider names are unique within a workspace. Use stable names because definitions files and other providers can refer to them."
    },
    {
      "id": "choose-a-provider",
      "title": "Choose a provider",
      "role": "content",
      "text": "A provider fills one or more literal roles: `offline-store`, `online-store`, `compute`, or `streaming`. Registration support doesn't mean every resource accepts every provider.\n\n| Provider | Roles | Use it for |\n| --- | --- | --- |\n| [Databricks](https://redis.io/docs/latest/develop/ai/featureform/register-providers/databricks) | `offline-store`, `compute` | Managed Spark compute with Unity Catalog outputs |\n| [Snowflake](https://redis.io/docs/latest/develop/ai/featureform/register-providers/snowflake) | `offline-store`, `compute` | Snowflake datasets and SQL compute |\n| [PostgreSQL](https://redis.io/docs/latest/develop/ai/featureform/register-providers/postgresql) | `offline-store`, `compute` | PostgreSQL datasets and SQL compute |\n| [S3](https://redis.io/docs/latest/develop/ai/featureform/register-providers/s3) | `offline-store` | Object storage and Spark data or staging access |\n| [Redis](https://redis.io/docs/latest/develop/ai/featureform/register-providers/redis) | `online-store` | Low-latency feature serving |\n| Spark | `compute` | Generic Spark execution |\n| Iceberg catalog | `offline-store` | Catalog-backed Iceberg tables |\n\nUse `ff provider register --help` to see the complete list of provider types and their current options."
    },
    {
      "id": "configure-secret-providers",
      "title": "Configure secret providers",
      "role": "configuration",
      "text": "Feature Form never stores credentials in any form. A provider configuration contains secret references, and the Feature Form process that needs a credential resolves it from the registered backend.\n\nEach workspace includes an `env` secret provider. An `env:PG_PASSWORD` reference reads `PG_PASSWORD` from the Feature Form server's environment, not from the shell where you run `ff`.\n\nCheck the built-in provider:\n\n[code example]\n\nFor production deployments, register the backend that manages your credentials before registering data providers that use it."
    },
    {
      "id": "register-an-environment-secret-provider",
      "title": "Register an environment secret provider",
      "role": "content",
      "text": "Use an environment provider for local development or bootstrap. A prefix helps separate its variables from other process configuration.\n\n**Python:**\n\n[code example]\n\n**ff CLI:**\n\n[code example]"
    },
    {
      "id": "register-vault",
      "title": "Register Vault",
      "role": "content",
      "text": "The Feature Form server must be able to authenticate to Vault. The provider uses the key-value version 2 secrets engine.\n\n**Python:**\n\n[code example]\n\n**ff CLI:**\n\n[code example]"
    },
    {
      "id": "register-kubernetes-secrets",
      "title": "Register Kubernetes secrets",
      "role": "content",
      "text": "For a Kubernetes deployment, use in-cluster authentication. The Feature Form server's service account needs permission to read secrets in the target namespace.\n\n**Python:**\n\n[code example]\n\n**ff CLI:**\n\n[code example]\n\n\n\nIf Feature Form runs outside Kubernetes, omit `in_cluster=True` or use `--no-k8s-in-cluster`. The Feature Form server then uses `~/.kube/config` and its current context. It doesn't use kubeconfig from the computer where you run `ff`."
    },
    {
      "id": "register-aws-secrets-manager",
      "title": "Register AWS Secrets Manager",
      "role": "content",
      "text": "The Feature Form server authenticates with the standard Amazon Web Services (AWS) credential chain.\n\n**Python:**\n\n[code example]\n\n**ff CLI:**\n\n[code example]"
    },
    {
      "id": "register-redis-for-online-serving",
      "title": "Register Redis for online serving",
      "role": "content",
      "text": "Register a `redis` or `redis-cluster` provider when feature views need an online store. See [Register Redis providers](https://redis.io/docs/latest/develop/ai/featureform/register-providers/redis) for topology, authentication, TLS, Spark, and Databricks guidance."
    },
    {
      "id": "keep-health-checks-enabled",
      "title": "Keep health checks enabled",
      "role": "content",
      "text": "Provider registration validates configuration and runs a synchronous health check before persistence by default. The exact check is provider-specific and might require write permissions.\n\nUse `--skip-health-check`, or `skip_health_check=True` in Python, only when the external system is deliberately unavailable during registration. This skips the synchronous check but does not disable recurring monitoring. Use `--disable-monitoring`, or `disable_monitoring=True`, to skip the initial check and disable recurring checks.\n\n> [!NOTE]\n> A successful health check verifies only the operations documented for that provider. It doesn't prove that every future dataset, table, policy, or workload is accessible."
    },
    {
      "id": "verify-registration",
      "title": "Verify registration",
      "role": "content",
      "text": "[code example]\n\nPass `--output json` or `--output yaml` for machine-readable output. If the provider isn't returned, rerun the registration command and review its validation or health-check error.\n\nIn Python, use `providers.list()` or `providers.get(\"<provider-name>\")`."
    },
    {
      "id": "update-or-delete-a-provider",
      "title": "Update or delete a provider",
      "role": "content",
      "text": "[code example]\n\nProvider-specific fields can be mutable, force-required, or immutable. `--force` allows a force-required change after Feature Form checks known direct uses. It doesn't override immutable fields, migrate external data, or guarantee that no indirect references exist. Review definitions and provider-to-provider references before an update or deletion.\n\nIn Python, use `providers.update()` and `providers.delete()`. Pass `force=True` to `providers.update()` only after the same review required for `--force`."
    },
    {
      "id": "automate-repeatable-registration",
      "title": "Automate repeatable registration",
      "role": "content",
      "text": "`register()` creates a provider and returns an error when that name already exists. For a repeatable automation script, register missing providers and update existing providers of the same type:\n\n[code example]\n\nYou can pass either `providers` or `secret_providers` as `registry`. The helper deliberately doesn't force an update. A force-required or immutable change fails so you can review its effect before changing the provider."
    },
    {
      "id": "next-steps",
      "title": "Next steps",
      "role": "content",
      "text": "After you register the required providers, [define and deploy features](https://redis.io/docs/latest/develop/ai/featureform/define-and-deploy-features)."
    }
  ],
  "examples": [
    {
      "id": "prerequisites-ex0",
      "language": "python",
      "code": "import featureform as ff\n\nclient = ff.Client.from_env()\nproviders = client.providers(\"<workspace-id>\")\nsecret_providers = client.secret_providers(\"<workspace-id>\")",
      "section_id": "prerequisites"
    },
    {
      "id": "configure-secret-providers-ex0",
      "language": "bash",
      "code": "ff secret-provider list --workspace <workspace-id>\nff secret-provider get env --workspace <workspace-id>",
      "section_id": "configure-secret-providers"
    },
    {
      "id": "register-an-environment-secret-provider-ex0",
      "language": "python",
      "code": "from featureform.types import EnvSecretConfig, SecretProviderType\n\nsecret_providers.register(\n    name=\"<secret-provider-name>\",\n    provider_type=SecretProviderType.ENV,\n    config=EnvSecretConfig(prefix=\"FF_\"),\n)",
      "section_id": "register-an-environment-secret-provider"
    },
    {
      "id": "register-an-environment-secret-provider-ex1",
      "language": "bash",
      "code": "ff secret-provider register <secret-provider-name> \\\n  --workspace <workspace-id> \\\n  --type env-var \\\n  --env-prefix FF_",
      "section_id": "register-an-environment-secret-provider"
    },
    {
      "id": "register-vault-ex0",
      "language": "python",
      "code": "from featureform.types import SecretProviderType, VaultSecretConfig\n\nsecret_providers.register(\n    name=\"<secret-provider-name>\",\n    provider_type=SecretProviderType.VAULT,\n    config=VaultSecretConfig(\n        address=\"https://<vault-host>\",\n        token_path=\"<vault-token-path>\",\n    ),\n)",
      "section_id": "register-vault"
    },
    {
      "id": "register-vault-ex1",
      "language": "bash",
      "code": "ff secret-provider register <secret-provider-name> \\\n  --workspace <workspace-id> \\\n  --type vault \\\n  --vault-address https://<vault-host> \\\n  --vault-token-path <vault-token-path>",
      "section_id": "register-vault"
    },
    {
      "id": "register-kubernetes-secrets-ex0",
      "language": "python",
      "code": "from featureform.types import KubernetesSecretConfig, SecretProviderType\n\nsecret_providers.register(\n    name=\"<secret-provider-name>\",\n    provider_type=SecretProviderType.K8S,\n    config=KubernetesSecretConfig(\n        namespace=\"<namespace>\",\n        secret_name=\"<secret-name>\",\n        in_cluster=True,\n    ),\n)",
      "section_id": "register-kubernetes-secrets"
    },
    {
      "id": "register-kubernetes-secrets-ex1",
      "language": "bash",
      "code": "ff secret-provider register <secret-provider-name> \\\n  --workspace <workspace-id> \\\n  --type k8s-secret \\\n  --k8s-namespace <namespace> \\\n  --k8s-secret-name <secret-name> \\\n  --k8s-in-cluster",
      "section_id": "register-kubernetes-secrets"
    },
    {
      "id": "register-aws-secrets-manager-ex0",
      "language": "python",
      "code": "from featureform.types import AWSSecretsManagerSecretConfig, SecretProviderType\n\nsecret_providers.register(\n    name=\"<secret-provider-name>\",\n    provider_type=SecretProviderType.AWS,\n    config=AWSSecretsManagerSecretConfig(region=\"<aws-region>\"),\n)",
      "section_id": "register-aws-secrets-manager"
    },
    {
      "id": "register-aws-secrets-manager-ex1",
      "language": "bash",
      "code": "ff secret-provider register <secret-provider-name> \\\n  --workspace <workspace-id> \\\n  --type aws-secrets-manager \\\n  --aws-region <aws-region>",
      "section_id": "register-aws-secrets-manager"
    },
    {
      "id": "verify-registration-ex0",
      "language": "bash",
      "code": "ff provider list --workspace <workspace-id>\nff provider get <provider-name> --workspace <workspace-id>",
      "section_id": "verify-registration"
    },
    {
      "id": "update-or-delete-a-provider-ex0",
      "language": "bash",
      "code": "ff provider update <provider-name> \\\n  --workspace <workspace-id> \\\n  <provider-options>\n\nff provider delete <provider-name> \\\n  --workspace <workspace-id>",
      "section_id": "update-or-delete-a-provider"
    },
    {
      "id": "automate-repeatable-registration-ex0",
      "language": "python",
      "code": "import featureform as ff\n\n\ndef ensure_registered(registry, name, provider_type, config):\n    try:\n        current = registry.get(name)\n    except ff.NotFoundError:\n        return registry.register(\n            name=name,\n            provider_type=provider_type,\n            config=config,\n        )\n\n    if current.type != provider_type:\n        raise ValueError(\n            f\"{name!r} is registered as {current.type}, not {provider_type}\"\n        )\n\n    return registry.update(\n        name=name,\n        config=config,\n        provider_type=provider_type,\n    )",
      "section_id": "automate-repeatable-registration"
    }
  ]
}
