How Langflow Manages Variables and Secret Storage: Database vs Kubernetes Options
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 specifies standard CRUD operations:
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 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.
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, credential encryption follows this pattern:
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 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 handles CRUD operations, including name encoding constraints:
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:
export LANGFLOW_VARIABLE_STORE=kubernetes
export LANGFLOW_KUBECONFIG=/path/to/kubeconfig
The factory implementation in src/backend/base/langflow/services/variable/factory.py resolves the backend at runtime:
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:
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:
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):
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:
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="[email protected]",
secrets={"credential_openai_api_key": "sk-...", "general_setting": "value"}
)
Summary
- Langflow manages variables through a
VariableServiceabstraction 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_keybefore persistence, decrypting on read. - Kubernetes storage maps each user to a secret named via
encode_user_id, prefixing credential keys withcredential_and relying on K8s RBAC for security. - Zero-downtime switching between backends is achieved via the
variable_storesetting andVariableServiceFactory. - 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 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.
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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →