Database

LongLink projects use standard SQLModel(opens in new tab) tables. Routes receive a Solution-scoped async SQLAlchemy(opens in new tab) database session as ctx.database by typing a route parameter as Context. Migrations are based on Alembic(opens in new tab).

TODO

Environment
Testing
memory SQLite database for isolated test runs.
Development
dev.db SQLite database for local development.
Production
PostgreSQL database using a schema scoped to the Solution.

Basic usage

python
from longlink import Context
from sqlmodel import Field, SQLModel
class Project(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
async def create_project(ctx: Context) -> None:
ctx.database.add(Project(name="Launch"))
await ctx.database.commit()

Timezone

Use LongLink's UTCDateTime type for datetime fields defined by your project. It requires a timezone-aware value and stores it in UTC.

python
from datetime import UTC, datetime
from sqlmodel import Field, SQLModel
from longlink.database.types import UTCDateTime
class Event(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
starts_at: datetime = Field(sa_type=UTCDateTime)
event = Event(starts_at=datetime(2026, 8, 3, 9, 0, tzinfo=UTC))

Audit table

Use AuditTable only when a database table needs Platform-user attribution. It adds creation, update, and deletion timestamps; the matching Platform user identifiers; and read-only user relationships.

python
from sqlmodel import Field
from longlink.database.base import AuditTable
class Approval(AuditTable, table=True):
id: int | None = Field(default=None, primary_key=True)
status: str
approval = Approval(status="pending")
print(approval.status) # pending
# approval.created_by and approval.updated_by are Audit users after persistence.

Migrations

After you add or change database models, run migrations to keep the schema aligned:

bash
uv run longlink migrate