{"id":6582,"library":"dbos","title":"DBOS Transact Python Library","description":"DBOS provides an ultra-lightweight Python library for durable execution, enabling fault-tolerant workflows and queues built on PostgreSQL (or SQLite by default). It allows developers to add resumable execution to applications using simple function annotations, eliminating the need for separate workflow orchestrators or task queue systems. As of version 2.18.0, it offers features like exactly-once execution, scheduled jobs, and built-in observability. The library is actively maintained with frequent updates and is suitable for building reliable backend services, data pipelines, and AI agents.","status":"active","version":"2.18.0","language":"en","source_language":"en","source_url":"https://github.com/dbos-inc/dbos-transact-py","tags":["durable execution","workflow","transactional","fault tolerance","postgres","queues","orchestration"],"install":[{"cmd":"pip install dbos","lang":"bash","label":"Core library"},{"cmd":"pip install dbos[otel]","lang":"bash","label":"With OpenTelemetry tracing"}],"dependencies":[{"reason":"ORM for database interactions, core dependency.","package":"sqlalchemy"},{"reason":"PostgreSQL adapter, used when connecting to PostgreSQL. For SQLite, it's not strictly needed but a compatible DBAPI is.","package":"psycopg","optional":true},{"reason":"For cron specification parsing in scheduled workflows.","package":"python-dateutil"},{"reason":"For parsing DBOS configuration files (e.g., dbos-config.yaml).","package":"pyyaml"},{"reason":"For CLI tooling.","package":"typer-slim"},{"reason":"For monitoring and UI integration.","package":"websockets"},{"reason":"Required for OpenTelemetry tracing features, installed with 'dbos[otel]'.","package":"opentelemetry-api","optional":true},{"reason":"Required for OpenTelemetry tracing features, installed with 'dbos[otel]'.","package":"opentelemetry-sdk","optional":true}],"imports":[{"symbol":"DBOS","correct":"from dbos import DBOS"}],"quickstart":{"code":"import os\nimport time\nfrom dbos import DBOS\n\n# Configure DBOS to use SQLite by default, or PostgreSQL if env var is set\n# For production, PostgreSQL is recommended. SQLite is good for local development.\ndbos_system_database_url = os.environ.get(\n    'DBOS_SYSTEM_DATABASE_URL',\n    'sqlite:///dbos_system.db'\n)\n\n# Initialize DBOS (this should typically happen once at application startup)\ndbos_instance = DBOS(system_database_url=dbos_system_database_url)\n\n@dbos_instance.step()\ndef greet_step(name: str) -> str:\n    \"\"\"A simple durable step that returns a greeting.\"\"\"\n    print(f\"Executing greet_step for {name}...\")\n    time.sleep(0.5) # Simulate some work\n    return f\"Hello, {name}!\"\n\n@dbos_instance.workflow()\ndef greeting_workflow(person_name: str) -> str:\n    \"\"\"A durable workflow composed of a single step.\"\"\"\n    print(f\"Starting greeting_workflow for {person_name}...\")\n    result = greet_step(person_name)\n    print(f\"Greeting workflow finished with: {result}\")\n    return result\n\nif __name__ == \"__main__\":\n    print(f\"DBOS System Database: {dbos_system_database_url}\")\n    try:\n        # Launch the DBOS application. This will discover and register workflows.\n        dbos_instance.launch()\n\n        # Start a workflow. DBOS ensures it will complete reliably.\n        workflow_handle = greeting_workflow.start(person_name=\"World\")\n\n        # You can optionally wait for the workflow to complete and get its result\n        final_result = workflow_handle.get_result()\n        print(f\"Workflow 'greeting_workflow' completed with result: {final_result}\")\n\n        # Demonstrate recovery: if you crash the app here, and restart, the workflow will resume\n        # For example, comment out the line above and uncomment the sleep and crash below, then restart.\n        # print(\"Sleeping for 10 seconds. Try to crash the app (Ctrl+C or kill) and restart it!\")\n        # time.sleep(10)\n        # workflow_handle = greeting_workflow.start(person_name=\"RecoveredUser\") # This will start a new one, but if the previous was pending, it would resume.\n\n    except KeyboardInterrupt:\n        print(\"Application interrupted.\")\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n    finally:\n        # Properly shut down DBOS resources\n        dbos_instance.destroy()\n        print(\"DBOS application shut down.\")","lang":"python","description":"This quickstart demonstrates a basic durable workflow using DBOS. It defines a `step` function and a `workflow` function, both decorated with DBOS annotations. The `DBOS` instance is initialized, optionally configured with a PostgreSQL connection string via the `DBOS_SYSTEM_DATABASE_URL` environment variable (defaults to SQLite). The `launch()` method registers the decorated functions, and `start()` initiates a workflow. DBOS automatically checkpoints the workflow's state, allowing it to recover from failures and resume from the last completed step upon restart."},"warnings":[{"fix":"Use DBOS's patching (`DBOS.patch()`) or versioning strategies to safely deploy changes without disrupting existing long-running workflows. Consult the 'Upgrading Workflow Code' documentation.","message":"Modifying the sequence or number of steps within an active workflow (a 'breaking change') can cause recovery failures for in-progress workflows. DBOS checkpoints the state of workflows in the database based on the expected flow.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure all workflow logic (excluding decorated steps, which handle their own non-determinism) is deterministic. Avoid direct I/O or random number generation inside workflow functions.","message":"DBOS workflows must be deterministic: given the same inputs, they must always invoke the same steps in the same order with the same inputs and expect the same return values from those steps. Non-deterministic workflows can lead to incorrect recovery behavior and `DBOSUnexpectedStepError`s.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all potentially blocking operations within an async DBOS application are properly awaited or run in an executor (e.g., `loop.run_in_executor`).","message":"Embedding synchronous (blocking) calls in Python or TypeScript asynchronous DBOS applications can block the event loop, preventing workflows and other async operations from making progress and leading to 'stuck' workflows.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Configure external API clients to have `max_retries=0` or similar to rely solely on DBOS's step retry policy.","message":"When using DBOS's retry mechanisms for steps that interact with external APIs, it's recommended to disable any built-in retry logic in the API client itself to avoid excessive or conflicting retries. For example, set `max_retries=0` for `OpenAIProvider` clients.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Verify that all data types used in workflow/step inputs/outputs are compatible with `pickle`. Keep payload sizes reasonable for optimal performance.","message":"Workflow inputs/outputs and step outputs are checkpointed using Python's `pickle` module. Ensure that all data passed through workflows or returned by steps is pickle-serializable. Large objects may also impact performance due to database write overhead.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure the PostgreSQL database (or SQLite file) is accessible before starting the DBOS application process. Implement infrastructure-level dependencies or retry mechanisms for application startup if database availability cannot be guaranteed.","message":"DBOS requires the system database to be available at application startup. If the configured database is unreachable during initialization, DBOS will exit rather than waiting for the connection to be established.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Each function should have a single primary DBOS decorator. Ensure unique names for functions registered with DBOS.","message":"Applying multiple DBOS decorators (e.g., `@DBOS.workflow()` and `@DBOS.transaction()`) to the same function or registering functions with conflicting names/types will raise a `DBOSConflictingRegistrationError`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}