docs/features/windows-postgresql-eventloop-fix.md
Generated on: 2024-02-13
Status: Approved
Owner: Platform Team / Database Infrastructure
This feature provides automatic event loop configuration for Windows systems running Langflow with PostgreSQL databases, resolving incompatibility between psycopg (PostgreSQL async driver) and Windows' default ProactorEventLoop.
Windows users experience application startup failures when using PostgreSQL as the database backend due to an incompatibility between the psycopg driver and Windows' default event loop implementation. This prevents Windows users from leveraging PostgreSQL's advanced features and scalability, limiting them to SQLite which may not meet enterprise requirements.
Platform Infrastructure - Database Connectivity Layer
| Term | Definition | Code Reference |
|---|---|---|
| Event Loop | The core async execution mechanism in Python that manages and executes asynchronous tasks | asyncio.get_event_loop_policy() |
| ProactorEventLoop | Windows' default event loop implementation using I/O Completion Ports | asyncio.WindowsProactorEventLoopPolicy |
| SelectorEventLoop | Alternative Windows event loop using select() system call, compatible with psycopg | asyncio.WindowsSelectorEventLoopPolicy |
| psycopg | PostgreSQL adapter for Python with async support | postgresql+psycopg:// |
| Event Loop Policy | Strategy pattern implementation controlling which event loop type is created | asyncio.set_event_loop_policy() |
| Database URL | Connection string specifying database type, credentials, and location | LANGFLOW_DATABASE_URL |
| Platform Detection | Runtime identification of the operating system | platform.system() |
WindowsPostgresHelperLANGFLOW_DATABASE_URL (constant)POSTGRESQL_PREFIXES (tuple constant)| Event | Trigger | Payload | Consumers |
|---|---|---|---|
| EventLoopConfigured | Windows + PostgreSQL detected | {event_loop: "WindowsSelectorEventLoop", reason: "psycopg_compatibility", source: str} | Logger (debug level) |
| ConfigurationSkipped | Non-Windows or non-PostgreSQL | None | None (silent) |
As a Windows user
I want Langflow to automatically configure the correct event loop
So that I can use PostgreSQL without encountering startup errors
Status: Accepted
The psycopg PostgreSQL driver is incompatible with Windows' default ProactorEventLoop, causing psycopg.InterfaceError during database connection initialization. The fix requires setting WindowsSelectorEventLoopPolicy before any async operations, but this was initially duplicated across multiple entry points.
Create a centralized helper function configure_windows_postgres_event_loop() that encapsulates all event loop configuration logic, following DRY (Don't Repeat Yourself) and Single Responsibility principles.
Benefits:
Trade-offs:
Impact on Product:
Status: Accepted
The event loop must be configured before any async operations or database imports. Langflow has multiple entry points: package import, launcher, main module, and service initialization.
Apply configuration at all critical entry points to ensure coverage regardless of how Langflow is started:
__init__.py - Package initializationlangflow_launcher.py - CLI launcher__main__.py - Direct module executionDatabaseService.__init__ - Service initializationinitialize_services() - Service orchestrationBenefits:
Trade-offs:
Impact on Product:
Status: Accepted
Uvicorn web server has its own event loop configuration that can override our settings when specified with loop="asyncio" parameter.
Conditionally set Uvicorn's loop parameter to None (use existing loop) when Windows + PostgreSQL is detected, allowing our pre-configured WindowsSelectorEventLoopPolicy to remain active.
Benefits:
Trade-offs:
Impact on Product:
| Type | Name | Purpose |
|---|---|---|
| Python Module | asyncio | Event loop management |
| Python Module | platform | OS detection |
| Python Module | os | Environment variable access |
| Library | psycopg | PostgreSQL async driver (external) |
| Library | sqlalchemy | Database abstraction layer |
| Service | DatabaseService | Database connection management |
| Logger | lfx.log.logger | Structured logging |
Purpose: Configures Windows event loop for PostgreSQL compatibility
Parameters:
source: str | None # Optional identifier for logging context (e.g., "main", "launcher")
Response (Success):
True # Event loop was configured
Response (No Action):
False # Configuration not needed or already configured
| Error Code | Condition | User Message | Recovery Action |
|---|---|---|---|
psycopg.InterfaceError | ProactorEventLoop with psycopg | "Psycopg cannot use the 'ProactorEventLoop'" | Automatic - helper prevents this error |
| N/A | Platform detection fails | Silent - returns False | No configuration applied, default behavior |
| N/A | Environment variable missing | Silent - returns False | No configuration applied, uses default |
| Metric | Type | Description | Alert Threshold |
|---|---|---|---|
event_loop_configuration_applied | Counter | Number of times configuration was applied | N/A - Informational |
event_loop_configuration_skipped | Counter | Number of times configuration was skipped | N/A - Informational |
database_connection_errors | Counter | PostgreSQL connection failures | > 5 per minute |
| Log Level | Event | Fields | When |
|---|---|---|---|
| DEBUG | Event loop configured | event_loop, reason, source | Configuration applied |
| INFO | PostgreSQL detected on Windows | database_url (sanitized) | Service initialization |
| ERROR | Database connection failed | error_type, platform | Connection failure |
| Flag | Purpose | Default | Rollout Strategy |
|---|---|---|---|
| N/A | Feature is always active when conditions are met | Enabled | Automatic based on platform + database detection |
C4Context
title System Context diagram for Windows PostgreSQL Event Loop Fix
Person(dev, "Developer", "Windows user running Langflow")
System(langflow, "Langflow", "AI application development platform")
System_Ext(postgres, "PostgreSQL", "Database server")
System_Ext(sqlite, "SQLite", "File-based database")
Rel(dev, langflow, "Develops AI apps")
Rel(langflow, postgres, "Stores data (with event loop fix)")
Rel(langflow, sqlite, "Alternative storage (no fix needed)")
C4Container
title Container diagram for Event Loop Configuration
Container(helper, "WindowsPostgresHelper", "Python Module", "Event loop configuration")
Container(launcher, "Launcher", "Python", "Application entry point")
Container(dbservice, "DatabaseService", "Python", "Database connection management")
ContainerDb(postgres, "PostgreSQL", "psycopg", "Async database connection")
Rel(launcher, helper, "Calls configure_windows_postgres_event_loop()")
Rel(dbservice, helper, "Calls configure_windows_postgres_event_loop()")
Rel(helper, postgres, "Configures compatible event loop")
Rel(dbservice, postgres, "Establishes connection")
graph TB
subgraph "Initialization Flow"
A[Application Start] --> B{Platform Check}
B -->|Windows| C{Database Check}
B -->|Linux/Mac| D[Skip Configuration]
C -->|PostgreSQL| E{Event Loop Check}
C -->|Other DB| D
E -->|ProactorEventLoop| F[Set SelectorEventLoop]
E -->|Already Selector| G[Skip - Already Set]
F --> H[Log Configuration]
G --> I[Return False]
H --> J[Return True]
D --> I
end
subgraph "Entry Points"
K[__init__.py] --> A
L[launcher.py] --> A
M[__main__.py] --> A
N[DatabaseService] --> A
O[initialize_services] --> A
end
No action required. The fix is automatically applied when:
LANGFLOW_DATABASE_URL starts with postgresql:// or postgres://No changes or impact. The fix only activates for Windows + PostgreSQL combinations.
Ensure LANGFLOW_DATABASE_URL is properly set in your .env file:
LANGFLOW_DATABASE_URL=postgresql://user:password@localhost:5432/langflow
Symptoms: psycopg.InterfaceError: Psycopg cannot use the 'ProactorEventLoop'
Solutions:
LANGFLOW_DATABASE_URL is properly set before application startSymptoms: Slower async operations on Windows after the fix
Context: SelectorEventLoop may have different performance characteristics than ProactorEventLoop
Solutions: