---
title: "Aktualisierung ohne Ausfallzeit"
description: "Aktualisieren Sie eine selbst gehostete Quire-Installation ohne Ausfallzeit."
image: "https://docs.quirelms.com/og.png"
---

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

# Aktualisierung ohne Ausfallzeit

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

Die Regeln stehen in Abschnitt 7 von `docs/architecture/23-ops.md` und in Abschnitt 4.1 von `docs/architecture/07-data.md`. Dies ist das Verfahren.

## Die Garantie, die das Verfahren sicher macht <!--quire:the-guarantee-that-makes-it-safe-->

**Version R funktioniert sowohl mit Schema R als auch mit Schema R minus eins.** Jede Schemaänderung wird in die Phasen Erweitern, Übergang und Bereinigen aufgeteilt:

1. **Erweitern**: Die neue Spalte, Tabelle oder der Index wird hinzugefügt. Der alte Code ignoriert sie.
2. **Übergang**, mindestens eine Version lang: Der neue Code schreibt beide Formen und liest die neue; ein fortsetzbarer Job füllt alte Zeilen nach.
3. **Bereinigen**: Die alte Form wird in einer späteren, allein dafür vorgesehenen Version entfernt.

Während eines rollierenden Upgrades können daher jederzeit alte und neue Prozesse dieselbe Datenbank verwenden. Es gibt keine Migrationen nach unten: Eine Migration, die vor einer Stunde eine Spalte entfernt hat, kann die in dieser Stunde geschriebenen Zeilen nicht zurückbringen.

Der CI-Job `schema-compat` prüft die Garantie bei jeder Version, indem er die Tests der vorherigen Version mit dem neuen Schema ausführt.

## Vor dem Start <!--quire:before-you-start-->

1. Lesen Sie die Versionshinweise. Eine Version, die ein Wartungsfenster benötigt, gibt dies samt Dauer an; pro Version gibt es höchstens eine solche Änderung.
2. Führen Sie die Wiederherstellungsübung durch oder vergewissern Sie sich, dass sie für diese Version erfolgreich abgeschlossen wurde ([backup-restore.md](/de/ops/backup-restore/)). Eine fehlgeschlagene Übung verhindert das Upgrade.
3. Erstellen Sie eine Basissicherung: `docker compose -f docker/compose.yaml --profile backup
   run --rm backup`.

## Docker Compose auf einem Host <!--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
```

Die Reihenfolge ist bewusst gewählt:

1. **Zuerst migrieren**, während die alte Version noch Anfragen bedient. Erweiterungen bleiben für sie unsichtbar.
2. **Danach den Web-Tier aktualisieren.** Bei SIGTERM setzt jeder Webprozess `/readyz` auf `draining`, beendet laufende Anfragen innerhalb von 30 Sekunden, schließt Streams mit einem Hinweis zum erneuten Verbinden und beendet sich. `stop_grace_period` beträgt 40 Sekunden, damit Compose einen ordnungsgemäßen Abbau nicht abbricht.
3. **Zuletzt die Worker**, damit zuerst die neueste Ereignisform erzeugt wird und dann der neueste Verbraucher sie erwartet. Worker beenden sofort das Abrufen von Jobs und erhalten 120 Sekunden Zeit. Kann ein Job nicht fertig werden, wird er anderswo erneut abgerufen. Das ist sicher, weil jeder Job idempotent ist. Der Scheduler übergibt die Führung beim nächsten Takt.

Auf einem einzelnen Host ersetzt Compose jeden Container der Reihe nach, sodass es für jeden Dienst eine kurze Unterbrechung gibt. Für einen unterbrechungsfreien Betrieb führen Sie den Web-Tier mit zwei Containern hinter Ihrem eigenen Proxy aus (eine Override-Datei ergänzt einen zweiten Web-Dienst ohne veröffentlichten Port) und erstellen Sie sie einzeln neu. Warten Sie jeweils, bis der Container den Status „healthy“ meldet.

## Mehrere Hosts oder ein Orchestrator <!--quire:several-hosts-or-an-orchestrator-->

Halten Sie dieselbe Reihenfolge ein: einmalig aus einem einzelnen Job migrieren, danach den Web-Tier mit einem zusätzlichen und null nicht verfügbaren Instanzen ausrollen, anschließend die Worker. Richten Sie Readiness-Prüfungen auf `/readyz` und Liveness-Prüfungen auf `/healthz`.

Bei dedizierten Mandantendatenbanken migriert der Schritt `migrate` beide Arten: zuerst die Kontrolldatenbank, dann nacheinander jede unter `ops.tenant_database` aufgeführte Datenbank, jeweils mit eigener Sperre. Ein Fehler in einer Mandantendatenbank hält die übrigen nicht auf. Sind alle Datenbanken bearbeitet, vergleicht der Vorgang die Migrationsprotokolle und wird mit einem Fehler beendet, wenn nicht jede Datenbank exakt dieselben Migrationen wie die Kontrolldatenbank angewendet hat. Dabei wird jede Datenbank genannt, die hinterherhinkt oder voraus ist. Derselbe Befehl installiert die Warteschlangentabellen in jeder Datenbank, da der Worker Jobs eines angehefteten Mandanten dort abholt, wo sie geschrieben wurden.

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```
Die normale Migration und die Ersteinrichtung installieren außerdem die kanonischen englischen Rechtsdokumente des Quire-Betreibers in `ops.platform_policy_version`. Das Installationsprogramm ist idempotent: Es werden nur fehlende englische Texte und genau die von der Migration angelegten Platzhaltertexte ersetzt. Die Ausgangsdaten werden archiviert und eine neue veröffentlichte Version eingefügt; historische Akzeptanzverweise und Texte bleiben erhalten. Jede echte, vom Betreiber verfasste Version, auch ein Entwurf, bleibt erhalten und muss über die Richtlinien-Konsole der Plattform verwaltet werden. Dokumente, Versionen und Einwilligung der Mandantenrichtlinien werden durch diese Umstellung niemals geändert. Dies ist die Veröffentlichung von Betreibertext, keine rechtliche Zertifizierung und keine automatische Erfüllung seiner Zusagen.


Jede dedizierte Datenbank wird über den Namen angesprochen, unter dem sie registriert ist. Eine unter `env:QUIRE_DB_NORTHWIND_URL` registrierte Datenbank benötigt:

| Variable | Verwendungszweck |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Anwendungsrolle für Web-Tier und Worker |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | Migrationsrolle für diesen Befehl und für Verschiebungen |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | Optional: Bootstrap (Rollen, Schemas und Hilfsfunktionen) vor der Migration erneut anwenden |

Eine registrierte Datenbank ohne `_MIGRATOR`-Verbindung wird als Fehler gemeldet und niemals übersprungen. Der Web-Tier kann ausgerollt werden, sobald die Kontrolldatenbank fertig ist. Eine um eine Stunde zurückliegende Mandantendatenbank erzeugt eine Warnung; nach einem Tag wird ein Alarm ausgelöst.

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

Ab Migration 0264 verwendet der Grounding-Korpus einen pgvector-HNSW-Index, sofern der Server die Erweiterung installiert hat. Der Compose-Dienst `postgres` wird damit erstellt (`docker/postgres.Dockerfile`). Beim ersten `migrate` nach dem Imagewechsel erstellt der Superuser-Bootstrap die Erweiterung; Migration 0264 fügt dann eine generierte Vektorspalte hinzu und erstellt den Index. Beim Hinzufügen wird `app.ai_chunk` einmal unter einer exklusiven Sperre neu geschrieben, daher warten Grounding-Anfragen darauf. Nichts anderes greift auf diese Tabelle zu.

Auf einem Server ohne pgvector protokolliert 0264 einen Hinweis und nimmt keine Änderungen vor; die Suche bleibt exakt. Bei pgvector vor Version 0.8 werden Spalte und Index zwar erstellt, die Suche bleibt aber exakt, bis die Erweiterung aktualisiert ist (`alter extension vector update`), denn gefilterte HNSW-Scans benötigen die iterativen Scans aus Version 0.8. So aktivieren Sie die Funktion später auf einem Server ohne pgvector: Installieren Sie die Erweiterung, führen Sie den Bootstrap erneut aus (oder rufen Sie als Superuser `create extension vector` auf) und führen Sie anschließend als `quire_migrator` Folgendes aus:

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

Der Vorgang ist idempotent und gibt `enabled` oder `unavailable` zurück. Führen Sie ihn auch in jeder dedizierten Mandantendatenbank aus.

## Rollback <!--quire:rolling-back-->

Ein **Code-Rollback** ist jederzeit möglich: Setzen Sie `QUIRE_RELEASE` auf das vorherige Tag und führen Sie erneut `up -d` aus. Das funktioniert, weil das Schema innerhalb einer Version in beide Richtungen kompatibel ist.

Ein **Schema-Rollback** wird nicht angeboten. Was sich nicht rückgängig machen lässt und wie Sie es beheben:

| Nicht umkehrbar | Wiederherstellung |
| --- | --- |
| Eine Bereinigungsmigration hat eine Spalte entfernt | Point-in-Time-Wiederherstellung vor dem Entfernen in eine neue Datenbank; Daten extrahieren und zusammenführen |
| Eine direkte Datenänderung | Ebenso, anschließend Schreibvorgänge abgleichen |
| Gesendete Webhooks und Ereignisse | Ausgleichsereignisse, niemals löschen |
| Gesendete E-Mail | Eine Person schreibt die Nachfassnachricht |
| Die Audit-Hash-Kette | Wird nie neu geschrieben; Korrektureintrag anhängen |

Deshalb wird eine Bereinigungsmigration allein ausgeliefert: Eine Wiederherstellung hat dann eine klare Grenze.

## Upgrade prüfen <!--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/de/ops/upgrade/index.mdx
