Skip to main content
Voir en Markdown

Infrastructure de base de données

Sovrium fonctionne sur une base de données SQLite embarquée avec zéro configuration et passe à PostgreSQL en définissant une seule variable d'environnement. L'intégralité du runtime — migrations, bundles client, le moteur CSS, les configurations d'exemple — est regroupée dans un seul binaire autonome, et un cache de rendu de page statique maintient le CPU du serveur frugal. Cette page documente la couche de persistance et de distribution qui rend possible « lancer le binaire, ouvrir l'URL ».

Valeur par défaut SQLite sans configuration

Lorsqu'aucune DATABASE_URL n'est définie, Sovrium résout le dialecte sqlite, crée ./.sovrium/database.db, applique automatiquement l'ensemble de migrations SQLite au premier démarrage et sert toute la surface de base — schéma, authentification, CRUD d'enregistrements, migrations et formulaires. La bannière de démarrage affiche Database: SQLite (<absolute path>).

Cela reflète la philosophie frugale-par-défaut de la plateforme (jumeau de STORAGE_PROVIDER et de la famille ECO_*) : l'opérateur opte pour PostgreSQL en définissant DATABASE_URL, jamais l'inverse.

PostgreSQL lorsqu'il est configuré

Définissez DATABASE_URL sur une URL postgresql:// et Sovrium résout le dialecte postgres, se connecte, applique l'ensemble de migrations PostgreSQL et affiche Database: PostgreSQL. Aucun fichier SQLite n'est créé. Ce chemin est identique octet pour octet aux déploiements PostgreSQL préexistants.

Une source unique de vérité — parseDatabaseDialectConfig() — discrimine par schéma l'unique variable DATABASE_URL :

Valeur de DATABASE_URL Se résout en
postgres://… / postgresql://… PostgreSQL à cette URL.
non définie / vide SQLite à ./.sovrium/database.db (la valeur par défaut sans configuration).
file:./x.db / file:/abs.db SQLite au chemin résolu.
sqlite:./x.db / sqlite:///abs.db Alias SQLite pour le même fichier sur disque.
:memory: SQLite éphémère (niveau dialecte uniquement — pas une cible de déploiement complète).
tout le reste (chemin nu, mysql://, …) Lève Unsupported DATABASE_URL scheme: … au démarrage (échec bruyant).

Le dialecte sélectionné pilote le client Drizzle (bun:sqlite ou bun:sql), l'ensemble de migrations, le fournisseur d'adaptateur Better Auth et l'étiquette runtime destinée à l'opérateur de GET /api/admin/config/version (sqlite-aio sur SQLite, postgres sur PostgreSQL).

Dégradation gracieuse

Le mode SQLite prend en charge le sous-ensemble de base. Les fonctionnalités avancées réservées à PostgreSQL — notamment la recherche sémantique RAG pgvector — renvoient un 501 { error: 'requires-postgres' } typé plutôt que de planter. Passez à PostgreSQL pour les débloquer ; aucune modification de code requise.

Répertoire de données embarqué

Tout l'état local vit sous un seul répertoire de données relocalisable.

Variable env Par défaut Description
DATABASE_URL non définie → SQLite Sélecteur de moteur + emplacement de base de données.
SOVRIUM_DATA_DIR ./.sovrium Racine du fichier de base de données SQLite, des fichiers de verrou et du stockage local. Relocalisez tout le répertoire de données avec une seule variable.

Le ./.sovrium/database.db par défaut se trouve sous ce répertoire de données ; le répertoire parent est créé automatiquement au premier démarrage.

Cache de rendu de page statique

Sovrium rend les pages côté serveur à chaque requête. Pour une page dont le HTML ne dépend pas de l'état par requête (une page marketing, à propos ou tarification), c'est du CPU gaspillé. Le cache de rendu en mémoire rend une telle page une fois et la sert depuis la mémoire lors des requêtes anonymes suivantes, en sautant entièrement renderToString — un gain d'écoconception et de latence.

Variable env Par défaut Options Description
ECO_PAGE_CACHE on on | off Cache en mémoire du HTML de page. Les opérateurs opèrent un opt-out ; ils n'opèrent jamais d'opt-in.
ECO_PAGE_CACHE_MAX_MB 64 entier (Mo) Budget mémoire du cache avant que les entrées les plus anciennes ne soient évincées.

Comment cela fonctionne :

  • La mise en cache est dérivée, jamais déclarée — sous la forme d'un verdict à trois valeurs. Une page est static lorsque son HTML rendu ne peut pas varier selon la requête. Une page est content lorsque sa seule entrée hors schéma est un répertoire de fichiers markdown : elle possède un contentDir et ne déclenche rien au-delà de contentDir, markdown et sa route :param. Tout le reste est dynamic et n'est jamais mis en cache — une page avec un access non public, une collection, un dataSource de page/composant, une source de fichier, une presence, une barre latérale liée aux données, ou une route :param sans contentDir derrière elle (il n'y a aucun corpus à mesurer, donc rien ne peut prouver l'invariance de son rendu).
  • Modèle de sécurité. Le cache n'est consulté que pour les requêtes anonymes, hors aperçu ; le filtrage dépendant de la session est déterministe lorsqu'aucune session n'existe, de sorte que la vue d'un utilisateur ne peut jamais fuiter vers un autre.
  • Invalidation par somme de contrôle. Chaque entrée est indexée par ${appRenderChecksum}:${path}:${language}. La somme de contrôle est un SHA-256 de la tranche de schéma affectant le rendu (pages, components, theme, languages, analytics) ; toute édition de schéma change chaque clé, de sorte que les entrées périmées deviennent inaccessibles. Aucune durée de vie, aucune logique de purge.
  • Les pages de contenu sont aussi indexées par leur corpus. Une page content étend cette clé avec une somme de contrôle de son contentDir : les tuples triés (chemin, mtimeMs, taille) de chaque fichier markdown, re-scannés à chaque requête (un glob plus un stat par fichier — environ 1-2 ms pour un corpus de 200 articles). Éditer, ajouter ou supprimer un article change la somme de contrôle, de sorte que la requête suivante manque le cache et sert la nouvelle prose. mtimeMs et taille participent tous deux, donc une réécriture de longueur différente à la même milliseconde est également détectée. Aucun observateur de fichiers, aucun redémarrage, aucun point de terminaison de purge.
  • Borné en octets, pas en nombre d'entrées. ECO_PAGE_CACHE_MAX_MB (par défaut 64) plafonne le HTML total conservé ; au-delà du budget, les entrées les plus anciennes dans l'ordre d'insertion sont évincées jusqu'à ce que la nouvelle entrée tienne, et une entrée plus grande que le budget entier est refusée. L'octet est la bonne unité dès lors que des zones de documentation entières deviennent cachables : 200 pages marketing et 200 articles de fond diffèrent d'un ordre de grandeur.
  • Observabilité. Chaque réponse de page porte X-Render-Cache: hit | miss | bypass et un en-tête Cache-Control : public, max-age=300 pour les pages cachables, public, max-age=60, stale-while-revalidate=300 pour les rendus anonymes de chemins non cachables (navigateurs et CDN peuvent les partager brièvement), et private, no-cache pour les rendus authentifiés ou en prévisualisation. Les variantes de langue (/ vs /fr/) sont isolées par clé.

Voir Écoconception pour le contrat complet des variables env ECO_*.

Distribution en binaire autonome

Le canal de distribution principal de Sovrium est un binaire autonome (bun build --compile) qui s'exécute sans Bun ni Node.js sur l'hôte cible. Le binaire embarque l'intégralité du runtime dans un seul exécutable :

  • Surface de commandes CLI (--version, validate, build, schema, init)
  • Ensembles de migrations (les deux dialectes)
  • Bundles client et chunks d'îlots
  • Modèles d'initialisation (chacun embarquant son propre bundle Claude Code) et configurations d'exemple
  • Le moteur CSS thématisé sans dépendance native

En mode compilé, le binaire lit ses assets embarqués, jamais les arborescences dist//src//specs/ du dépôt sur disque — de sorte qu'il se comporte de façon identique lorsqu'il est lancé depuis n'importe quel répertoire de travail sur une machine cliente. Les bundles client embarqués, les chunks d'îlots et le script de changement de langue sont servis via HTTP depuis un serveur lancé par le binaire (GET /assets/output.css, GET /assets/client.js, GET /assets/islands/*).

Pages connexes

Dernière mise à jour 11 août 2026

Cette documentation a été rédigée avec de l'IA : des erreurs ou du contenu obsolète sont donc possibles. Sovrium est en bêta. Les contributions et corrections sont les bienvenues.

Construit avec Sovrium