# 0006 — MySQL 8 floor; tests run on MySQL

**Status:** Accepted · 2026-08-01

## Context

Shared hosting offers a wide spread of MySQL and MariaDB versions. Supporting all
of them means avoiding `utf8mb4` index-length pain on 5.7, working around weak
JSON support, and testing a matrix we cannot actually verify.

Separately, the Laravel default is to run tests against SQLite in memory. It is
much faster.

## Decision

**MySQL 8.0 is the floor.** The installer refuses to proceed below it, with a
clear message, rather than installing and failing subtly months later on a
customer's server. `utf8mb4_0900_ai_ci`, InnoDB, `ROW_FORMAT=DYNAMIC`. MariaDB
10.6+ compatibility is a nice-to-have, so we avoid MySQL-8-only syntax in
application queries where a fallback exists.

**Tests run against MySQL**, not SQLite. `phpunit.xml` points at a `clinic_test`
database.

## Consequences

**Good.** The schema uses enums, fulltext indexes, `SELECT ... FOR UPDATE` and
NULL-sensitive unique indexes. A green SQLite suite would prove nothing about any
of them — that is precisely how "passed CI, broke on the customer's server"
happens, and with hundreds of installations we cannot SSH into, that failure mode
is unusually expensive.

The audit-chain JSON canonicalisation bug recorded in ADR 0005 is a concrete
example: it is a MySQL JSON-column behaviour and would not exist on SQLite.
Testing on SQLite would have shipped it.

**Bad.** The suite is slower and requires a running MySQL server. Accepted
without hesitation.

**Bad.** Some prospective customers on old shared hosting are excluded. Also
accepted: supporting them costs more in support hours than their licences are
worth, and a "host compatibility checker" published pre-sale turns that into a
qualifying question rather than a refund.
