← Docs

SQLAlchemy

Drop-in SQLAlchemy wrapper that routes queries through Gold Lapel. Covers the SQLAlchemy Core engine, the ORM, and async apps like FastAPI.

Install

pip install goldlapel sqlalchemy

# Plus a Postgres driver of your choice:
pip install psycopg2-binary   # sync
pip install psycopg            # psycopg3 (sync or async)
pip install asyncpg            # async

The SQLAlchemy glue ships inside the goldlapel package at goldlapel.sqlalchemy — no extra install step. Install SQLAlchemy separately with regular pip.

Quick Start (sync)

Import from goldlapel.sqlalchemy instead of sqlalchemy — everything else stays the same. The L1 native cache activates automatically — repeated reads serve in microseconds.

Before
from sqlalchemy import create_engine
engine = create_engine("postgresql://user:pass@host:5432/mydb")
After
from goldlapel.sqlalchemy import create_engine
engine = create_engine("postgresql://user:pass@host:5432/mydb")

Full sync example:

from goldlapel.sqlalchemy import create_engine
from sqlalchemy import text

engine = create_engine("postgresql://user:pass@host:5432/mydb")

# That's it — queries now route through Gold Lapel
with engine.connect() as conn:
    result = conn.execute(text("SELECT * FROM users"))

Quick Start (async)

Use create_async_engine for async applications. Dialect suffixes like +asyncpg are handled automatically:

from goldlapel.sqlalchemy import create_async_engine
from sqlalchemy import text

engine = create_async_engine("postgresql+asyncpg://user:pass@host:5432/mydb")

async with engine.connect() as conn:
    result = await conn.execute(text("SELECT * FROM users"))

The sync Engine path uses the in-process L1 native cache (microsecond reads). AsyncEngine queries still route through the Gold Lapel proxy for L2 caching and optimization — native L1 cache for async engines lands in a follow-up release.

SQLAlchemy ORM

The ORM sits on top of the engine, so once the engine is wired through Gold Lapel, everything above it — Session, declarative models, Query, select(), relationships — flows through automatically:

from goldlapel.sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Session, Mapped, mapped_column

class Base(DeclarativeBase): ...

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str]

engine = create_engine("postgresql://user:pass@host:5432/mydb")

with Session(engine) as session:
    users = session.query(User).filter(User.email.like("%@example.com")).all()

FastAPI Example

A complete async setup with session management:

from fastapi import FastAPI
from goldlapel.sqlalchemy import create_async_engine
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy import text

engine = create_async_engine("postgresql+asyncpg://user:pass@host:5432/mydb")
SessionLocal = async_sessionmaker(engine)

app = FastAPI()

@app.get("/users")
async def list_users():
    async with SessionLocal() as session:
        result = await session.execute(text("SELECT * FROM users"))
        return result.mappings().all()

Alternative: init()

Rewrites DATABASE_URL to route through the proxy, so you can create your own engine as usual:

import goldlapel.sqlalchemy
import os

goldlapel.sqlalchemy.init()

# Now create your engine as usual — it connects through Gold Lapel
from sqlalchemy import create_engine
engine = create_engine(os.environ["DATABASE_URL"])

Options

Optional proxy settings via keyword arguments on create_engine / create_async_engine:

engine = create_engine(
    "postgresql://user:pass@host:5432/mydb",
    goldlapel_port=9000,
    goldlapel_config={"mode": "waiter", "pool_size": 50},
    goldlapel_extra_args=["--threshold-duration-ms", "200"],
)
KeyDefaultDescription
goldlapel_port7932Local proxy port
goldlapel_configNoneFull Gold Lapel config dict (same keys as goldlapel.start(config=...))
goldlapel_extra_args[]Extra CLI flags passed to the Gold Lapel binary

The same options are available on init() with shorter names:

goldlapel.sqlalchemy.init(
    port=9000,
    config={"mode": "waiter", "pool_size": 50},
    extra_args=["--threshold-duration-ms", "200"],
)
KeyDefaultDescription
port7932Local proxy port
configNoneFull Gold Lapel config dict
extra_args[]Extra CLI flags passed to the Gold Lapel binary

Dialect Suffixes

SQLAlchemy dialect suffixes (+asyncpg, +psycopg, +pg8000) are handled automatically. Pass your normal SQLAlchemy connection URL — Gold Lapel strips the suffix when building the upstream connection and preserves it for the local proxy connection.

Advanced Tuning

goldlapel_config takes the same dict as goldlapel.start(config=...) — see the configuration reference for every setting. goldlapel_extra_args and GOLDLAPEL_* environment variables both work as secondary escape hatches.

Requirements

  • Python 3.9+
  • SQLAlchemy 1.4+
  • goldlapel 0.2+
  • PostgreSQL (TCP connections only)

Upgrading from v0.1

The goldlapel[sqlalchemy] install extra was removed in v0.2. SQLAlchemy is now installed separately, and the glue code always ships inside the main goldlapel package:

# v0.1.x (old) — single pinned install extra
pip install goldlapel[sqlalchemy]

# v0.2 (new) — install goldlapel and sqlalchemy separately
pip install goldlapel sqlalchemy
  • Install command changed — pip install goldlapel[sqlalchemy] is gone. Install goldlapel and sqlalchemy separately.
  • Import path is unchanged — from goldlapel.sqlalchemy import create_engine still works.
  • Keyword arguments on create_engine (goldlapel_port, goldlapel_extra_args) are unchanged. goldlapel_config is the newly exposed full-config passthrough.
  • Internally the wrapper now calls the new goldlapel.start() factory — behaviour is identical to v0.1 from SQLAlchemy's perspective.

How It Works

goldlapel.sqlalchemy wraps SQLAlchemy's create_engine and create_async_engine functions. When you create an engine, it extracts the database connection details from your URL, calls goldlapel.start() to spawn the proxy, and wires a connection with the L1 native cache into the engine (sync path). All subsequent queries — via Core or the ORM — flow through Gold Lapel automatically.

The init() alternative takes a different approach — it rewrites DATABASE_URL in your environment so that any engine you create afterward connects through the proxy without needing the wrapper import.