Tables

Every table is pithy_<capability>_<table>, and that prefix is the same segment that is the pithy add argument, the migration namespace, the error-code domain, the audit-action domain and the catalog key.

One rule, five places — so one capability’s tables cannot collide with another’s, or with yours.

Your own tables carry no pithy_ prefix. That is what keeps them yours.

Every table here is created by migrations, reached through the data layer, and lives in whichever database its binding resolves to — which is how two Workers come to share one.

auth

pithy_auth_users · pithy_auth_accounts · pithy_auth_sessions · pithy_auth_verifications · pithy_auth_jwks · pithy_auth_rate_limit · pithy_auth_devices · pithy_auth_rotated_tokens

The first six are Better Auth’s, created from its own schema. The last two are the kit’s — the device registry and the refresh-token reuse ledger.

pithy_auth_users.locale is the one home for a person’s language, and it is nullable: null means nobody chose, which is a different fact from en.

payments

pithy_payments_purchases · pithy_payments_entitlements · pithy_payments_provider_accounts · pithy_payments_webhook_events · pithy_payments_reconcile_runs · pithy_payments_sync_cursors

Two constraints carry the design. UNIQUE (rail, providerTransactionId) on purchases is the idempotency anchor all three write paths rely on; UNIQUE (rail, providerEventId) on webhook events is what makes a redelivery recognized rather than reprocessed.

storage

pithy_storage_objects · pithy_storage_shares

A share is a row rather than a presigned URL, because a presigned URL cannot be revoked.

media

pithy_media_assets · pithy_media_hashes

email

pithy_email_jobs · pithy_email_events · pithy_email_suppressions

The suppression table lives in its own binding, shared across a project’s environments. The other two are per environment.

vector

pithy_vector_documents — the corpus. The embeddings live in Vectorize; long source text belongs here, which is why this capability has a table at all.

secrets

pithy_secrets_system_secrets · pithy_secrets_rotations

In their own database, because the master key that opens the rows is per environment.

support

pithy_support_threads · pithy_support_messages · pithy_support_classifications · pithy_support_attachments · pithy_support_thread_flags

testers

pithy_testers_cohorts · pithy_testers_members · pithy_testers_events · pithy_testers_cohort_snapshots

The events table is append-only, and the streak is replayed from it — never stored as a counter, because a counter can only be overwritten, which destroys both the old value and the evidence that it changed.

One snapshot per cohort per UTC day is what makes the trend chartable: the opt-in figures could always be replayed, activity could not.

audit

pithy_audit_events — append-only. No route deletes, edits or prunes.

ledger

pithy_ledger_accounts · pithy_ledger_transactions · pithy_ledger_holds

CHECK (balance >= 0 AND held >= 0 AND held <= balance) on accounts is the overdraft guard, and ref is UNIQUE across the whole ledger.

leaderboard

pithy_leaderboard_boards · pithy_leaderboard_entries · pithy_leaderboard_locks

The lock table is the advisory lock that keeps at most one rank refresh running.

rating

pithy_rating_ratings — one row per (pool, player). The skill column is indexed, because bucketing a matchmaking queue is a range read over it.

matchmaking

pithy_matchmaking_invites · pithy_matchmaking_friends

The friend graph is indexed both ways, so a lookup from either side is one read.

multiplayer

pithy_multiplayer_results — one row per terminal session. Session and game state live in the Durable Object’s own storage, not here.

the control plane

pithy_controlplane_connections · pithy_controlplane_replays

The replay table is keyed on the token id alone, never the pair of token and connection — a composite would let a token captured from one connection be spent against another.

bookkeeping

pithy_migrations_owner — the ownership stamp.

An unstamped database is adopted on first migrate; your own is a no-op, and somebody else’s is caught rather than migrated into.

ESC