Skip to content

Broker Config

from horsies import PostgresConfig
broker = PostgresConfig(
database_url="postgresql+psycopg://user:password@localhost:5432/mydb",
)
FieldTypeDefaultDescription
database_urlstrrequiredSQLAlchemy connection URL
session_database_urlstr | NoneNoneDirect/session-capable URL for schema setup and LISTEN/NOTIFY
pgbouncer_transaction_modeboolFalseDisable prepared statements for transaction-pooled PgBouncer
pool_sizeint30Connection pool size
max_overflowint30Additional connections beyond pool_size
pool_timeoutint30Seconds to wait for connection
pool_pre_pingboolTruePre-ping connections before use
echoboolFalseEcho SQL statements to logs
pool_recycleint1800Recycle connections after N seconds
postgresql+psycopg://user:password@host:port/database

Components:

  • postgresql+psycopg - Driver (psycopg3)
  • user:password - Credentials
  • host:port - Server location (default port: 5432)
  • database - Database name
PostgresConfig(
database_url="postgresql+psycopg://postgres:postgres@localhost:5432/horsies_dev",
)
PostgresConfig(
database_url="postgresql+psycopg://app:secret@db.example.com:5432/production",
pool_size=10,
max_overflow=20,
pool_timeout=30,
pool_recycle=3600,
)
import os
PostgresConfig(
database_url=os.environ["DATABASE_URL"],
)

Use a split configuration when the main SQL URL points to PgBouncer transaction pooling. database_url is used for ordinary SQL work. session_database_url is used for schema setup and PostgreSQL LISTEN/NOTIFY, which need persistent session semantics.

from horsies import AppConfig, PostgresConfig
config = AppConfig(
broker=PostgresConfig(
database_url=os.environ["DATABASE_URL_POOLED"],
session_database_url=os.environ["DATABASE_URL_DIRECT"],
pgbouncer_transaction_mode=True,
),
)

Some managed providers, including PlanetScale Postgres, expose separate pooled and direct connection strings. Treat provider-specific ports and hostnames as an example, not a Horsies requirement. Check your provider dashboard or current provider docs and copy the pooled transaction URL into database_url and the direct/session-capable URL into session_database_url.

Rules:

  • Workers require session_database_url when pgbouncer_transaction_mode=True.
  • Syce requires the session URL for real-time updates.
  • PgBouncer-only worker deployment is unsupported.
  • Horsies does not infer PgBouncer mode from port numbers.

The broker uses SQLAlchemy’s async connection pool:

  • pool_size: Base number of persistent connections
  • max_overflow: Additional connections created under load (temporary)
  • pool_timeout: How long to wait if all connections are busy
  • pool_recycle: Close and recreate connections after this many seconds
Deploymentpool_sizemax_overflow
Development2-55
Small production5-1010-20
High traffic10-2020-40

Consider: pool_size + max_overflow should not exceed PostgreSQL’s max_connections (divided by number of worker processes).

The broker creates two connection types:

  1. Async engine (SQLAlchemy): For queries, inserts, updates
  2. LISTEN/NOTIFY (psycopg): For real-time notifications

By default both use database_url. With split PgBouncer configuration, ordinary SQL uses database_url, while schema setup and LISTEN/NOTIFY use session_database_url.

The broker includes automatic health checks:

  • Proactive connection monitoring
  • Auto-reconnect on connection loss
  • Exponential backoff for reconnection attempts

On first use, the broker creates required tables:

  • horsies_tasks - Task storage
  • horsies_heartbeats - Liveness tracking
  • horsies_worker_states - Worker monitoring
  • horsies_schedule_state - Scheduler state

Uses PostgreSQL advisory locks to prevent race conditions during schema creation.