---
title: "Mise à niveau sans interruption"
description: "Mettez à niveau Quire auto-hébergé sans interruption."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/fr/llms.txt
> Use this file to discover all available pages before exploring further.

# Mise à niveau sans interruption

<span id="upgrading-without-downtime"></span>

Les règles figurent à la section 7 de `docs/architecture/23-ops.md` et à la section 4.1 de `docs/architecture/07-data.md`. Voici la procédure.

## La garantie qui rend l’opération sûre <!--quire:the-guarantee-that-makes-it-safe-->

**La version R fonctionne correctement avec le schéma R et avec le schéma R moins un.** Chaque changement de schéma est réparti entre les phases d’extension, de transition et de retrait :

1. **Extension** : ajoutez la nouvelle colonne, table ou index. L’ancien code l’ignore.
2. **Transition**, pendant au moins une version : le nouveau code écrit les deux structures et lit la nouvelle ; un travail reprenable complète les anciennes lignes.
3. **Retrait** : supprimez l’ancienne structure, seule, dans une version ultérieure.

Ainsi, à chaque instant d’une mise à niveau progressive, les anciens et les nouveaux processus peuvent partager une base de données. Il n’y a pas de migration descendante : une migration qui a supprimé une colonne il y a une heure ne peut pas rétablir les lignes écrites pendant cette heure.

À chaque version, le travail CI `schema-compat` vérifie cette garantie en exécutant les tests de la version précédente avec le nouveau schéma.

## Avant de commencer <!--quire:before-you-start-->

1. Lisez les notes de version. Une version nécessitant une fenêtre de maintenance l’indique, avec une estimation ; il n’y en a au plus qu’une par version.
2. Exécutez le test de restauration ou vérifiez qu’il a réussi pour cette version ([backup-restore.md](/fr/ops/backup-restore/)). Un test échoué bloque la mise à niveau.
3. Effectuez une sauvegarde de base : `docker compose -f docker/compose.yaml --profile backup
   run --rm backup`.

## Docker Compose, un seul hôte <!--quire:docker-compose-one-host-->

```sh
export QUIRE_RELEASE=2026.10.0            # or set it in docker/.env
docker compose -f docker/compose.yaml pull   # or build
docker compose -f docker/compose.yaml run --rm migrate
docker compose -f docker/compose.yaml up -d --no-deps web content collab
docker compose -f docker/compose.yaml up -d --no-deps worker scheduler
```

L’ordre est délibéré :

1. **Migrez d’abord**, pendant que l’ancienne version sert le trafic. Les migrations d’extension lui sont invisibles.
2. **Mettez ensuite à jour la couche Web.** À la réception de SIGTERM, chaque processus Web fait passer `/readyz` à l’état `draining`, termine les requêtes en cours en 30 secondes, ferme les flux en indiquant au client de se reconnecter, puis se termine. `stop_grace_period` est fixé à 40 secondes afin que Compose n’interrompe jamais un arrêt sain.
3. **Mettez les workers à jour en dernier** : la forme d’événement la plus récente est ainsi produite avant que le consommateur le plus récent ne l’attende. Les workers cessent immédiatement de récupérer des travaux et disposent de 120 secondes ; un travail non terminé est récupéré ailleurs, ce qui est sûr puisque chaque travail est idempotent. Le scheduler transfère le leadership à son prochain tick.

Sur un seul hôte, Compose remplace les conteneurs à tour de rôle, ce qui crée une courte interruption pour chaque service. Pour n’avoir aucune interruption, exécutez deux conteneurs Web derrière votre proxy (un fichier de surcharge ajoutant un second service Web sans port publié) et recréez-les un par un, en attendant que chacun soit sain avant de passer au suivant.

## Plusieurs hôtes ou un orchestrateur <!--quire:several-hosts-or-an-orchestrator-->

Respectez le même ordre : migrez une fois depuis un travail unique, mettez progressivement à jour la couche Web avec une instance supplémentaire et aucune instance indisponible, puis les workers. Pointez les sondes de disponibilité sur `/readyz` et celles de vitalité sur `/healthz`.

Avec des bases dédiées aux locataires, l’étape `migrate` fait les deux opérations : elle migre d’abord la base de contrôle, puis chaque base répertoriée dans `ops.tenant_database`, une par une et chacune sous son propre verrou. Une erreur dans une base de locataire n’arrête pas les autres. Lorsque toutes sont traitées, le processus compare les registres de migration et renvoie un code de sortie non nul si chaque base n’a pas exactement les mêmes migrations appliquées que la base de contrôle ; il nomme alors les bases en retard ou en avance. La même commande installe les tables de file dans chaque base, car le worker consomme les travaux d’un locataire épinglé là où ils ont été écrits.

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```
La migration normale et la configuration initiale installent également les documents juridiques anglais canoniques de l'opérateur Quire dans `ops.platform_policy_version`. Le programme d'installation est idempotent : seuls les textes anglais manquants et exactement les textes temporaires créés par la migration sont remplacés. Les données initiales sont archivées et une nouvelle version publiée est insérée ; les références d'acceptation historiques et les textes sont conservés. Toute version authentique rédigée par l'opérateur, y compris un brouillon, est préservée et doit être gérée via la console Stratégies de la plateforme. Les documents, versions et consentement des stratégies des locataires ne sont jamais modifiés par cette transition. Il s'agit de la publication du texte de l'opérateur, et non d'une certification juridique ni de l'exécution automatique de ses promesses.


Chaque base dédiée est contactée par le nom sous lequel elle est enregistrée. Une base enregistrée sous `env:QUIRE_DB_NORTHWIND_URL` nécessite :

| Variable | Utilisation |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Rôle applicatif pour la couche Web et le worker |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | Rôle de migrateur pour cette commande et les déplacements |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | Facultatif : réapplique l’initialisation (rôles, schémas, assistants) avant la migration |

Une base enregistrée sans connexion `_MIGRATOR` est signalée en échec, jamais ignorée. La mise à jour progressive de la couche Web peut commencer lorsque la base de contrôle est migrée. Une base de locataire en retard d’une heure déclenche un avertissement ; après un jour, une alerte est envoyée.

## pgvector <!--quire:pgvector-->

À partir de la migration 0264, le corpus d’ancrage utilise un index HNSW pgvector si le serveur dispose de l’extension ; le service Compose `postgres` est compilé avec celle-ci (`docker/postgres.Dockerfile`). Le premier `migrate` après le changement d’image crée l’extension au moyen de l’initialisation superutilisateur ; 0264 ajoute ensuite une colonne vectorielle générée et crée l’index. L’ajout de la colonne réécrit une fois `app.ai_chunk` sous verrou exclusif ; les requêtes d’ancrage attendent donc, et rien d’autre ne touche cette table.

Sur un serveur sans pgvector, 0264 consigne une notice et ne modifie rien ; la recherche reste exacte. Avec une version de pgvector antérieure à 0.8, la colonne et l’index sont créés mais la recherche reste exacte jusqu’à la mise à niveau de l’extension (`alter extension vector update`), car les scans HNSW filtrés nécessitent les scans itératifs de la version 0.8. Pour l’activer ultérieurement sur un serveur qui en est dépourvu, installez l’extension, relancez l’initialisation (ou exécutez `create extension vector` en tant que superutilisateur), puis, en tant que `quire_migrator` :

```sql
set maintenance_work_mem = '1GB';  -- the HNSW build is much faster in memory
select ops.ai_chunk_enable_vector_index();
```

L’opération est idempotente et renvoie `enabled` ou `unavailable`. Exécutez-la également sur chaque base dédiée de locataire.

## Retour à une version antérieure <!--quire:rolling-back-->

Le retour à une version antérieure du **code** est toujours possible : définissez `QUIRE_RELEASE` sur l’étiquette précédente et relancez `up -d`. Cela fonctionne, car le schéma est compatible dans les deux sens au sein d’une version.

Le retour à un ancien **schéma** n’est pas proposé. Voici les changements irréversibles et les méthodes de récupération :

| Changement irréversible | Récupération |
| --- | --- |
| Migration de retrait ayant supprimé une colonne | Restauration à un instant antérieur à la suppression dans une nouvelle base, extraction et fusion des données |
| Modification directe des données | Même méthode, puis rapprochement des écritures intervenues depuis |
| Webhooks et événements envoyés | Événements compensatoires, jamais une suppression |
| E-mails envoyés | Une personne rédige le message de suivi |
| Chaîne de hachage d’audit | Ne jamais la réécrire ; ajouter une entrée de correction |

C’est pourquoi une migration de retrait est livrée seule : la restauration dispose alors d’une limite nette.

## Vérifier la mise à niveau <!--quire:checking-the-upgrade-->

```sh
docker compose -f docker/compose.yaml ps           # every service healthy
curl -fsS http://localhost:8080/readyz             # ready, and what is configured
docker compose -f docker/compose.yaml logs migrate # the migrations applied
```

Source: https://docs.quirelms.com/fr/ops/upgrade/index.mdx
