# How Langflow Manages Variables and Secret Storage: Database vs Kubernetes Options

> Discover how Langflow manages variables and secrets using database or Kubernetes options. Explore secure storage solutions for your Langflow projects.

- Repository: [Langflow/langflow](https://github.com/langflow-ai/langflow)
- Tags: deep-dive
- Published: 2026-02-24

---

**Langflow abstracts variable lifecycle management behind a `VariableService` interface that supports both encrypted SQL database persistence and native Kubernetes Opaque secrets, configurable via the `variable_store` setting.**

Langflow treats variables as named values referenced in flow components using Mustache syntax (e.g., `{{my_var}}`). In the `langflow-ai/langflow` repository, the platform provides a pluggable storage architecture that allows operators to choose between local database encryption or enterprise-grade Kubernetes secret management based on deployment requirements.

## Variable Service Architecture

Langflow implements a clean service abstraction that decouples the flow execution engine from underlying storage mechanisms. The **Variable Service** defines a common API contract used throughout the codebase, enabling seamless swapping between backends without modifying component logic.

The base interface in [`src/lfx/src/lfx/services/variable/service.py`](https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/services/variable/service.py) specifies standard CRUD operations:

```python
class VariableService(Service):
    def get_variable(self, name: str, **kwargs) -> str | None: ...
    def set_variable(self, name: str, value: str, **kwargs) -> None: ...
    def delete_variable(self, name: str, **kwargs) -> None: ...
    def list_variables(self, **kwargs) -> list[str]: ...

```

Concrete implementations reside in separate modules. The `VariableServiceFactory` in [`src/backend/base/langflow/services/variable/factory.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/factory.py) instantiates the appropriate backend based on runtime configuration, returning either `DatabaseVariableService` or `KubernetesSecretService` to calling code.

## Storage Backend Options

Langflow supports two primary storage backends for variable persistence, selectable via the `variable_store` configuration setting defined in [`src/lfx/src/lfx/services/settings/base.py`](https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/services/settings/base.py).

### Database Storage with Encryption

The default `DatabaseVariableService` persists variables as SQLModel rows in the Langflow database. When storing **credential** type variables, the service automatically encrypts values before insertion using the Auth service utilities.

In [`src/backend/base/langflow/services/variable/service.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/service.py), credential encryption follows this pattern:

```python
if variable.type == CREDENTIAL_TYPE:
    variable.value = auth_utils.encrypt_api_key(value, settings_service=self.settings_service)

```

Decryption occurs transparently during retrieval via `auth_utils.decrypt_api_key`, ensuring API keys and sensitive tokens never exist in plaintext within the database.

### Kubernetes Secret Storage

For cloud-native deployments, `KubernetesSecretService` in [`src/backend/base/langflow/services/variable/kubernetes.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/kubernetes.py) persists variables as Kubernetes **Opaque** secrets. Each user receives a dedicated secret named via `encode_user_id` to satisfy DNS-1123 compliance (≤253 characters, alphanumeric boundaries).

Credential variables receive a `credential_` prefix when stored in Kubernetes. Unlike the database backend, Kubernetes storage relies on the platform's native RBAC and at-rest encryption rather than application-level encryption. The low-level `KubernetesSecretManager` in [`src/backend/base/langflow/services/variable/kubernetes_secrets.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/kubernetes_secrets.py) handles CRUD operations, including name encoding constraints:

```python
def encode_user_id(user_id: UUID | str) -> str:
    # Handles UUIDs, email-style IDs, and generic strings

    # Replaces forbidden chars, truncates to 253, ensures leading/trailing alphanumerics

```

## Configuration and Environment Setup

Switching between storage backends requires no code changes—only environment configuration. The default `variable_store="db"` can be overridden via the `LANGFLOW_VARIABLE_STORE` environment variable or YAML configuration:

```bash
export LANGFLOW_VARIABLE_STORE=kubernetes
export LANGFLOW_KUBECONFIG=/path/to/kubeconfig

```

The factory implementation in [`src/backend/base/langflow/services/variable/factory.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/factory.py) resolves the backend at runtime:

```python
if settings_service.settings.variable_store == "kubernetes":
    from langflow.services.variable.kubernetes import KubernetesSecretService
    return KubernetesSecretService(settings_service)
return DatabaseVariableService(settings_service)

```

## Fallback and Import Mechanisms

Langflow provides graceful degradation when variables are missing from the primary store. When `fallback_to_env_var` is enabled (the default), the service queries OS environment variables before returning `None`:

```python
value = os.getenv(name)  # Fallback path in src/lfx/src/lfx/services/variable/service.py

```

Additionally, setting `store_environment_variables=True` triggers automatic import of variables listed in `variables_to_get_from_environment` from the OS into the selected store during startup, simplifying local development workflows.

## Practical Implementation Examples

### Retrieving Variables (Backend Agnostic)

Access variables using the dependency helper regardless of underlying storage:

```python
from langflow.services import get_variable_service

async def fetch_api_key(user_id: str):
    var_service = await get_variable_service()
    value = await var_service.get_variable(
        user_id=user_id,
        name="openai_api_key",
        field="value",
        session=None
    )
    return value

```

### Storing Encrypted Credentials

Create credential variables that automatically encrypt (DB) or prefix (Kubernetes):

```python
from uuid import UUID
from langflow.services import get_variable_service

async def store_secret(user_id: UUID, api_key: str):
    var_service = await get_variable_service()
    await var_service.create_variable(
        user_id=user_id,
        name="openai_api_key",
        value=api_key,
        default_fields=[],
        type_="credential",
        session=None,
    )

```

### Manual Kubernetes Secret Creation

For direct secret management without the service layer:

```python
from langflow.services.variable.kubernetes_secrets import KubernetesSecretManager, encode_user_id

def provision_user_secrets(user_id: str, secrets: dict[str, str]):
    manager = KubernetesSecretManager(namespace="langflow")
    secret_name = encode_user_id(user_id)
    manager.create_secret(name=secret_name, data=secrets)

# Usage

provision_user_secrets(
    user_id="alice@example.com",
    secrets={"credential_openai_api_key": "sk-...", "general_setting": "value"}
)

```

## Summary

- **Langflow manages variables** through a `VariableService` abstraction that hides storage implementation details from flow components.
- **Two storage backends** are available: encrypted SQL database (default) and Kubernetes Opaque secrets (cloud-native).
- **Database storage** encrypts credential variables using `auth_utils.encrypt_api_key` before persistence, decrypting on read.
- **Kubernetes storage** maps each user to a secret named via `encode_user_id`, prefixing credential keys with `credential_` and relying on K8s RBAC for security.
- **Zero-downtime switching** between backends is achieved via the `variable_store` setting and `VariableServiceFactory`.
- **Environment fallback** allows variables to resolve from OS environment variables when not found in the primary store.

## Frequently Asked Questions

### How do I switch Langflow from database to Kubernetes secret storage?

Set the environment variable `LANGFLOW_VARIABLE_STORE=kubernetes` and ensure `LANGFLOW_KUBECONFIG` points to a valid kubeconfig file. The `VariableServiceFactory` in [`src/backend/base/langflow/services/variable/factory.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/factory.py) automatically instantiates `KubernetesSecretService` instead of `DatabaseVariableService` on the next startup.

### Are credential variables encrypted when using Kubernetes secrets?

No. When using the Kubernetes backend, credential variables are stored as base64-encoded values within Opaque secrets with a `credential_` prefix, but they are not application-encrypted. Kubernetes provides security through its own RBAC policies and cluster-level encryption at rest. For application-level encryption, use the database backend which calls `auth_utils.encrypt_api_key` in [`src/backend/base/langflow/services/auth/utils.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/auth/utils.py).

### What happens if a variable is not found in the configured store?

If `fallback_to_env_var` is enabled in settings (the default behavior), Langflow queries the OS environment variable with the same name before returning `None`. This mechanism is implemented in the base `VariableService` class and applies to both database and Kubernetes storage backends.

### How does Langflow handle Kubernetes naming constraints for secrets?

The `encode_user_id` function in [`src/backend/base/langflow/services/variable/kubernetes_secrets.py`](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/services/variable/kubernetes_secrets.py) sanitizes user IDs to comply with DNS-1123 standards: limiting length to 253 characters, replacing forbidden characters, and ensuring alphanumeric start/end characters. This allows email-based user IDs and UUIDs to function as valid Kubernetes secret names.