# Supported databases

Source: https://docs.externa.qiick.io/docs/supported-databases

Externa supports four first-class Laravel drivers. CI runs Pest on all of them; production prefers PostgreSQL.

## Compatibility matrix

| Database       | Min version   | Preferred  | Role                                                           |
| -------------- | ------------- | ---------- | -------------------------------------------------------------- |
| **SQLite**     | 3.x (PHP PDO) | —          | Local / CI / demos. **Not** for multi-writer production.       |
| **PostgreSQL** | 14+           | **16+**    | **Production recommended** (jsonb + GIN on collection values). |
| **MySQL**      | **8.0+**      | 8.4        | Production supported.                                          |
| **MariaDB**    | **10.6+**     | **10.11+** | Production supported (`DB_CONNECTION=mariadb`).                |

Out of scope: MySQL 5.7, MariaDB &lt; 10.6, SQL Server, Oracle.

## Charset (MySQL / MariaDB)

Use **`utf8mb4`** with collation **`utf8mb4_unicode_ci`** (Laravel `config/database.php` defaults via `DB_CHARSET` / `DB_COLLATION`). Do not use `utf8` / `utf8mb3`.

## CI coverage

GitHub Actions (`.github/workflows/tests.yml` in externa-core):

| Job          | Driver                           |
| ------------ | -------------------------------- |
| `ci`         | SQLite in-memory (PHP 8.4 + 8.5) |
| `ci-mysql`   | MySQL 8.4                        |
| `ci-mariadb` | MariaDB 11.4                     |
| `ci-pgsql`   | PostgreSQL 16                    |

Browser tests stay on SQLite.

## Postgres-only features

Collection value indexes use **GIN** (`jsonb_path_ops`) only on PostgreSQL. MySQL/MariaDB use standard Laravel `json` columns without a GIN equivalent — heavy JSON filter workloads prefer Postgres.

MySQL/MariaDB **JSON** columns may reorder object keys on write; Externa treats JSON as unordered maps (tests use equality, not identity).

## Driver selection

Set `DB_CONNECTION` to one of: `sqlite` | `pgsql` | `mysql` | `mariadb`.

```env
# MySQL 8 example
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=externa
DB_USERNAME=externa
DB_PASSWORD=secret
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
```

```env
# MariaDB (Laravel mariadb driver)
DB_CONNECTION=mariadb
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=externa
DB_USERNAME=externa
DB_PASSWORD=secret
```

Create the empty database (and user) before `php artisan migrate`. Full env catalog: [Environment variables](/docs/environment-variables). Local examples: [Quick Start](/docs/quick-start), [Installation](/docs/installation). Production swap: [Deployment](/docs/deployment#production-database-leave-sqlite).

## Related

- [Environment variables](/docs/environment-variables) — `DB_*`
- [Quick Start](/docs/quick-start) — Herd Postgres / MySQL snippets
- [Installation](/docs/installation) · [Deployment](/docs/deployment)
- [Testing](/docs/testing) — Pest + RefreshDatabase
