This page documents the service layer of the Langflow backend: the set of long-lived singleton services that underpin the application, how they are registered, initialized, and torn down, and the dependency injection mechanism used to access them from API endpoints and other modules.
For the configuration values that services read at startup, see Backend Settings Service. For the database schema and ORM models that services operate on, see Database Layer. For how create_app() and the lifespan hook integrate with this layer, see Application Lifecycle.
All application-level singletons are managed through a central service registry. Services are identified by values in the ServiceType enum (langflow.services.schema.ServiceType) and retrieved via helper functions defined in langflow.services.deps.
This pattern means:
Depends(get_db_service) etc.; non-FastAPI code calls the same functions directly.Core modules:
| Module | Role |
|---|---|
langflow.services.schema | ServiceType enum — the canonical name for every service |
langflow.services.base | Service abstract base class |
langflow.services.deps | get_service(), get_db_service(), get_auth_service(), session_scope(), etc. |
langflow.services.utils | initialize_services(), initialize_settings_service(), teardown_services() |
Sources: src/backend/base/langflow/services/utils.py1-25 src/backend/base/langflow/main.py42-51
Services registered at startup (inferred from deps imports across the codebase):
| Service | ServiceType name | Primary file | Purpose |
|---|---|---|---|
| Settings | SETTINGS_SERVICE | lfx.services.settings (re-exported via langflow.services.settings.base) | Pydantic settings model; loaded from env/yaml before all others |
| Database | DATABASE_SERVICE | langflow.services.database.service.DatabaseService | Async SQLAlchemy engine, session factory, Alembic migrations |
| Auth | AUTH_SERVICE | langflow.services.auth / lfx.services.auth.service | JWT signing, password hashing, API key validation |
| Cache | CACHE_SERVICE | langflow.services.cache | In-process or external async cache for flows and components |
| Storage | STORAGE_SERVICE | langflow.services.storage.service.StorageService | Local or S3-backed file storage |
| Variable | VARIABLE_SERVICE | langflow.services.variable | Global variable (credential) store per user |
| Telemetry | TELEMETRY_SERVICE | langflow.services.telemetry | Background telemetry and exception reporting |
| Queue | QUEUE_SERVICE | langflow.services.queue | Async task / event queue |
| MCP Composer | (lfx-side) | lfx.services.mcp_composer.service.MCPComposerService | MCP server composition and lifecycle |
Sources: src/backend/base/langflow/services/utils.py1-20 src/backend/base/langflow/main.py42-52 src/backend/base/langflow/initial_setup/setup.py50-56 src/backend/base/langflow/__main__.py37-39 src/backend/base/langflow/services/settings/base.py1-16
Title: Service initialization flow inside get_lifespan and the startup lifespan context
The key ordering constraint is that initialize_settings_service() is called before the lifespan context is entered, so that get_settings_service() is usable immediately by get_telemetry_service() at module level src/backend/base/langflow/main.py147-153
Sources: src/backend/base/langflow/main.py147-175 src/backend/base/langflow/services/utils.py1-60 src/backend/base/langflow/services/database/service.py42-79
DatabaseService — DetailedDatabaseService (in langflow.services.database.service) is the most complex service. It owns the SQLAlchemy async engine and session factory, and runs Alembic migrations on startup.
Class attributes and constructor behavior:
DatabaseService
name = "database_service"
settings_service ← injected SettingsService
database_url ← sanitized URL (sqlite+aiosqlite, postgresql+psycopg, …)
engine ← AsyncEngine (created via _create_engine or retry variant)
async_session_maker ← async_sessionmaker(engine, class_=SQLModelAsyncSession)
script_location ← path to /alembic
alembic_cfg_path ← path to alembic.ini
URL sanitization happens in _sanitize_database_url(): plain sqlite:// is rewritten to sqlite+aiosqlite://, and postgresql:// (or postgres://) is rewritten to postgresql+psycopg:// src/backend/base/langflow/services/database/service.py111-128
Connection pool settings are taken from settings.db_connection_settings dict, with deprecated top-level pool_size and max_overflow settings merged on top as overrides src/backend/base/langflow/services/database/service.py130-148
Alembic migrations are run inside initialize_services(). The log destination is controlled by settings.alembic_log_to_stdout and settings.alembic_log_file src/backend/base/langflow/services/database/service.py80-96
Sources: src/backend/base/langflow/services/database/service.py42-110
SettingsService — DetailedThe settings module at langflow.services.settings.base is a thin re-export of lfx.services.settings.base:
Settings — Pydantic settings model populated from environment variables and optional YAML config fileCustomSource — custom Pydantic settings source for YAML loadingload_settings_from_yaml / save_settings_to_yaml — YAML I/O helpersis_list_of_any — utility for multi-type field coercioninitialize_settings_service() (in langflow.services.utils) constructs SettingsService and registers it in the global service registry before any other service is created, because DatabaseService, AuthService, and others all receive it as a constructor argument.
Sources: src/backend/base/langflow/services/settings/base.py1-16 src/backend/base/langflow/main.py147-153
Title: How code accesses services — deps.py function-to-service mapping
All functions are imported from langflow.services.deps. FastAPI routes declare them as Depends(get_db_service) etc. Non-FastAPI code (setup, CLI, tests) calls them directly.
is_settings_service_initialized() exists for the CLI, which must check whether settings have been bootstrapped before calling other helpers src/backend/base/langflow/__main__.py37
Sources: src/backend/base/langflow/main.py42-51 src/backend/base/langflow/__main__.py37-39 src/backend/base/langflow/initial_setup/setup.py50-56 src/backend/base/langflow/services/utils.py19-20
session_scope — Database Session Context Managersession_scope() is an async context manager (defined in langflow.services.deps, originally sourced from lfx.services.deps) that provides a fully managed AsyncSession:
Internally it calls DatabaseService.async_session_maker to create a SQLModelAsyncSession (SQLModel's async session subclass, which adds the .exec() method over plain SQLAlchemy). The session is committed on success and rolled back on exception.
session_scope is used in:
initialize_agentic_global_variables) src/backend/base/langflow/main.py237-242create_or_update_starter_projects) src/backend/base/langflow/initial_setup/setup.py50-56Depends(session_scope) or direct useSources: src/backend/base/langflow/services/database/service.py72-78 src/backend/base/langflow/main.py237-242
Title: Constructor-level service dependencies
SettingsService is a root dependency — every other service either receives it via constructor injection or reads it through get_settings_service(). DatabaseService is the second-order dependency for any service that needs to persist or read data.
Sources: src/backend/base/langflow/services/database/service.py45-48 src/backend/base/langflow/services/utils.py1-60 src/backend/base/langflow/main.py147-175
teardown_services() (imported from langflow.services.utils) is called inside the shutdown branch of the lifespan async context manager in main.py. Its responsibilities include:
TelemetryService and QueueServiceMCPComposerServiceteardown_superuser() is a separate helper (imported in langflow.services.database.service) that removes the default superuser account if it was auto-created, used when AUTO_LOGIN mode is disabled.
Sources: src/backend/base/langflow/main.py147-175 src/backend/base/langflow/services/database/service.py35-37 src/backend/base/langflow/services/utils.py1-30
The auth service exposes utilities consumed directly by the setup and CLI layers:
| Function | Module | Purpose |
|---|---|---|
get_or_create_super_user() | langflow.services.utils | Upserts the default superuser at startup |
teardown_superuser() | langflow.services.utils | Removes the auto-created superuser on shutdown |
create_super_user() | langflow.services.auth.utils | Creates a superuser record in the DB |
get_current_user_from_access_token() | langflow.services.auth.utils | Decodes JWT and resolves User |
check_key() | langflow.services.database.models.api_key.crud | Validates an API key against the DB |
get_or_create_super_user calls get_auth_service() internally to hash and verify passwords, demonstrating how utility functions use the registry rather than constructing services directly src/backend/base/langflow/services/utils.py26-55
Sources: src/backend/base/langflow/services/utils.py26-55 src/backend/base/langflow/__main__.py35-39
langflow.services.cache provides two tiers:
| Class | When used |
|---|---|
AsyncInMemoryCacheService | Default; process-local LRU cache |
ExternalAsyncBaseCacheService | When an external store (e.g., Redis) is configured |
CacheServiceFactory (imported in services/utils.py) selects the correct implementation at startup based on settings.cache_type. The cache stores serialized flow graphs and component type dictionaries to avoid recomputing them on every request.
Sources: src/backend/base/langflow/services/utils.py12-13
The MCPComposerService (defined in lfx.services.mcp_composer.service) manages the lifecycle of MCP (Model Context Protocol) servers associated with individual flows. It is started as a background asyncio task during lifespan and stopped during teardown. The init hook for per-project MCP servers is init_mcp_servers() from langflow.api.v1.mcp_projects.
Sources: src/backend/base/langflow/main.py250-260 pyproject.toml333-336
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.