Skip to main content

Database Schema

Nenyax uses PostgreSQL with SQLAlchemy ORM and Alembic migrations.

Dual User Table Design

Nenyax maintains two separate user-related tables. This is intentional: Why two tables? The users table acts as an auth-agnostic abstraction layer. If the auth provider changes (e.g., switching from Better Auth to Auth.js or a custom solution), only the sync logic needs updating — all business data, foreign keys, and queries remain untouched. How they sync: When a user signs up via Better Auth and makes their first API request, the backend automatically creates a corresponding users row by reading from Better Auth’s "user" table. This auto-creation happens in verify_session_token() in backend/app/dependencies.py. Organization auto-creation follows the same pattern: Better Auth manages the "organization" table, and the backend auto-creates a corresponding organizations row on first access (see _auto_create_org_from_ba() in dependencies.py).

Tables

instance_settings

Encrypted API key store (instance-level, not per-user). Managed via API Keys in the dashboard.

users

Backend user records, auto-created from Better Auth on first authenticated request.

agents

Voice agent configurations. The config JSON column stores the complete agent configuration:

voice_sessions

Call session records.

transcripts

Per-message conversation logs.

usage_events

Granular cost tracking events logged by the agent worker.

agent_files

Files uploaded for custom agents, stored in MinIO.

agent_file_versions

Version history for custom agent files.

agent_containers

Docker container tracking for custom agents.

coding_agent_conversations

Chat conversations with the coding agent (per agent, per user).

coding_agent_messages

Individual messages within coding agent conversations.

organizations

Multi-tenancy: top-level tenant for resource scoping. Auto-created from Better Auth’s "organization" table on first access.

org_members

Organization membership with roles.

org_api_keys

Per-organization encrypted API key storage.

user_api_keys

Per-user encrypted API key storage (legacy, migrating to org_api_keys).

Migrations

Database migrations are managed by Alembic and run automatically on backend startup:

Fresh Deployment Notes

On a fresh deployment, the backend runs alembic upgrade head on startup to create all tables. If migrations fail, the backend will not start — check the logs for migration errors. Startup order matters: In Docker Compose, PostgreSQL must be healthy before the backend starts. The frontend can start independently since Better Auth tables are created via autoMigrate() in the frontend’s auth.ts.

Better Auth Tables

Better Auth manages its own tables ("user", "session", "account", "verification", "organization", "member", "invitation"). These are created automatically by the frontend’s auth configuration. Do not modify these tables via Alembic — they are owned by Better Auth.