Skip to content
Last updated May 15, 2026

Database Setup

PromptGate uses Laravel Eloquent and works against any database Laravel supports. Out of the box you get SQLite, which is perfect for single-instance / local / small-team setups. When you outgrow that, swap to MySQL 8+ or PostgreSQL 14+.

Use caseRecommendation
Local dev, getting-started, single-user prodSQLite (default)
Single-host prod with one app containerSQLite still fine, or MySQL/Postgres if you prefer
Multi-host or reverse-proxied across replicasPostgreSQL or MySQL
You already run Postgres elsewherePostgreSQL
You already run MySQLMySQL 8+

SQLite is more capable than people think — at the gateway-log volumes most teams generate, it’ll outperform a poorly-tuned MySQL on the same hardware. Don’t switch just because “real” databases sound more serious.

No setup required. The default .env:

Terminal window
DB_CONNECTION=sqlite
DB_DATABASE=database/database.sqlite

The file is created automatically on php artisan migrate. With Docker Compose it lives in backend/database/database.sqlite on the host (mounted into the container at /app/database/database.sqlite).

Pros: zero ops, fast small queries, embedded, easy to back up (cp the file). Cons: one writer at a time (writes serialise inside the file lock), no replication.

The simplest backup is to copy the file while the app is idle. For a hot backup:

Terminal window
docker compose exec app sqlite3 database/database.sqlite ".backup database/snapshot.sqlite"

Or use the Backup / Export admin page, which dumps every table as JSON regardless of the underlying engine — that’s portable across engines too.

If you don’t already have one, add it to your Compose file:

services:
app:
# ... existing app config
depends_on:
- mysql
environment:
DB_CONNECTION: mysql
DB_HOST: mysql
DB_PORT: '3306'
DB_DATABASE: promptgate
DB_USERNAME: promptgate
DB_PASSWORD: changeme
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: promptgate
MYSQL_USER: promptgate
MYSQL_PASSWORD: changeme
MYSQL_ROOT_PASSWORD: changeme-root
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
Terminal window
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=promptgate
DB_USERNAME=promptgate
DB_PASSWORD=changeme
Terminal window
docker compose down
docker compose up -d
docker compose exec app php artisan migrate --force
docker compose exec app php artisan db:seed --force

If you already have data in SQLite that you want to keep:

Terminal window
# 1. Take a backup (admin → Backup / Export)
# 2. Stop the app
docker compose stop app
# 3. Update .env to point at MySQL
# 4. Boot fresh schema in MySQL
docker compose start app
docker compose exec app php artisan migrate --force
# 5. Restore from your JSON backup ZIP
# (Restore is a manual process today — use the JSON dumps with
# artisan tinker to insert rows. A first-class restore command
# is on the roadmap.)
services:
app:
depends_on:
- postgres
environment:
DB_CONNECTION: pgsql
DB_HOST: postgres
DB_PORT: '5432'
DB_DATABASE: promptgate
DB_USERNAME: promptgate
DB_PASSWORD: changeme
postgres:
image: postgres:16
environment:
POSTGRES_DB: promptgate
POSTGRES_USER: promptgate
POSTGRES_PASSWORD: changeme
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
Terminal window
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=promptgate
DB_USERNAME=promptgate
DB_PASSWORD=changeme

Same procedure as MySQL — php artisan migrate --force rebuilds the schema.

Laravel uses one connection per request out of the box. For high-throughput gateways, switch to PgBouncer (Postgres) or ProxySQL (MySQL) with transaction-level pooling.

The migrations ship with all indexes the gateway needs at typical traffic. If you’re doing heavy reporting on gateway_logs, consider adding:

-- Postgres / MySQL
CREATE INDEX gateway_logs_created_endpoint_idx
ON gateway_logs (created_at DESC, endpoint_id);

This speeds up the per-endpoint metrics page when the table grows past a few million rows.

gateway_logs accumulates one row per request. For a busy gateway, prune monthly:

Terminal window
docker compose exec app php artisan tinker
# inside tinker:
\App\Models\GatewayLog::query()->where('created_at', '<', now()->subDays(90))->delete();

A scheduled prune command is on the roadmap; until then, run this from cron.

Whatever engine you use, back up regularly. The admin Backup / Export page produces a portable ZIP that’s engine-agnostic and small (because it skips logs by default).

For native dumps:

Terminal window
# SQLite
cp backend/database/database.sqlite backups/promptgate-$(date +%F).sqlite
# MySQL
docker compose exec mysql mysqldump -u promptgate -p promptgate > backups/promptgate-$(date +%F).sql
# Postgres
docker compose exec postgres pg_dump -U promptgate promptgate > backups/promptgate-$(date +%F).sql

Next: Architecture — the mental model.


© Akyros Labs LLC. All rights reserved.

Was this page helpful?