---
title: "Oppgradere uten nedetid"
description: "Oppgrader en selvdrevet Quire uten nedetid."
image: "https://docs.quirelms.com/og.png"
---

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

# Oppgradere uten nedetid

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

Reglene står i `docs/architecture/23-ops.md` seksjon 7 og `docs/architecture/07-data.md` seksjon 4.1. Dette er prosedyren.

## Garantien som gjør det trygt <!--quire:the-guarantee-that-makes-it-safe-->

**Utgivelse R kjører korrekt mot skjema R og skjema R minus én.** Hver skjemendring deles i utvide, overgang og kontrakt:

1. **Utvid**: legg til den nye kolonnen, tabellen eller indeksen. Gammel kode ignorerer den.
2. **Overgang**, i minst én utgivelse: ny kode skriver begge former og leser den nye; en gjenopptakbar jobb etterfyller gamle rader.
3. **Kontrakt**: fjern den gamle formen, i en senere utgivelse, alene.

Så i hvert øyeblikk av en rullerende oppgradering kan gamle og nye prosesser dele én database. Det finnes ingen nedmigreringer: en migrering som fjernet en kolonne for en time siden kan ikke gi tilbake radene skrevet i den timen.

`schema-compat`-CI-jobben sjekker garantien på hver utgivelse ved å kjøre forrige utgivelses tester mot det nye skjemaet.

## Før du starter <!--quire:before-you-start-->

1. Les utgivelsesnotatene. En utgivelse som trenger et vedlikeholdsvindu sier det, med anslaget; høyst ett per utgivelse.
2. Kjør gjenopprettingsøvelsen, eller bekreft at den kjørte grønt for denne utgivelsen ([backup-restore.md](/nb/ops/backup-restore/)). En mislykket øvelse blokkerer oppgraderingen.
3. Ta en basesikkerhetskopi: `docker compose -f docker/compose.yaml --profile backup run --rm backup`.

## Docker Compose, én vert <!--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
```

Rekkefølgen er bevisst:

1. **Migrer først**, mens den gamle utgivelsen betjener trafikk. Utvidelsesmigreringer er usynlige for den.
2. **Webnivået deretter.** Ved SIGTERM vipper hver webprosess `/readyz` til `draining`, fullfører pågående forespørsler innen 30 sekunder, lukker strømmer med et gjenkoblingstips, og avslutter. `stop_grace_period` er 40 sekunder slik at Compose aldri kutter en sunn tømming.
3. **Arbeiderne sist**, slik at den nyeste hendelsesformen produseres før den nyeste forbrukeren forventer den. Arbeidere slutter å hente med én gang og får 120 sekunder; en jobb som ikke kan fullføres hentes igjen et annet sted, noe som er trygt fordi hver jobb er idempotent. Planleggeren overleverer lederskapet ved neste tick.

På én vert erstatter Compose hver container etter tur, så det er et kort gap per tjeneste. For intet gap i det hele tatt, kjør webnivået som to containere bak din egen proxy (en overstyringsfil som legger til en andre webtjeneste uten publisert port), og gjenskap dem én om gangen, og vent til hver melder sunn før den neste.

## Flere verter eller en orkestrator <!--quire:several-hosts-or-an-orchestrator-->

Bruk samme rekkefølge: migrer én gang fra én jobb, rull deretter webnivået med én ekstra og null utilgjengelige, deretter arbeiderne. Pek beredskapssonder mot `/readyz` og livlighet mot `/healthz`.

Med dedikerte tenantdatabaser gjør `migrate`-steget begge: det migrerer kontrolldatabasen først, deretter hver database listet i `ops.tenant_database`, én om gangen, hver under sin egen lås. En feil i én tenantdatabase stopper ikke de andre. Når alle databaser er ferdige sammenligner det migreringshovedbøkene og avslutter med feil med mindre alle databaser har brukt nøyaktig migreringene kontrolldatabasen har, og navngir hver som ligger bak eller foran. Samme kommando installerer køtabellene i hver database, fordi arbeideren forbruker en festet tenants jobber der de ble skrevet.

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```
Vanlig migrering og førstegangsoppsett installerer også de kanoniske engelske juridiske dokumentene fra Quire-operatøren i `ops.platform_policy_version`. Installasjonsprogrammet er idempotent: bare manglende engelske tekster og nøyaktig de plassholdertekstene som migreringen opprettet, erstattes. Frø arkiveres, og en ny publisert versjon settes inn; historiske akseptreferanser og tekster beholdes. Enhver ekte operatørskrevet versjon, også et utkast, bevares og må forvaltes via plattformens policy-konsoll. Leietakerens policydokumenter, versjoner og samtykke endres aldri av denne overgangen. Dette er publisering av operatørtekst, ikke juridisk sertifisering eller automatisk oppfyllelse av dens løfter.


Hver dedikerte database nås gjennom navnet den er registrert under. En database registrert som `env:QUIRE_DB_NORTHWIND_URL` trenger:

| Variabel | Brukt til |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Applikasjonsrollen, for webnivået og arbeideren |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | Migratorrollen, for denne kommandoen og for flyttinger |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | Valgfri: gjenbruker oppstarten (roller, skjemaer, hjelpere) før migrering |

En registrert database uten `_MIGRATOR`-tilkobling rapporteres som en feil, hoppes aldri over. Webnivået kan rulle når kontrolldatabasen er ferdig. En tenantdatabase som ligger en time bak varsler; et døgn varsler med personsøker.

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

Fra migrering 0264 bruker jordingskorpuset en pgvector HNSW-indeks der tjeneren har utvidelsen; Compose-`postgres`-tjenesten bygges med den (`docker/postgres.Dockerfile`). Den første `migrate` etter bytte av bilder oppretter utvidelsen gjennom superbruker-oppstarten, og 0264 legger deretter til en generert vektorkolonne og bygger indeksen. Å legge til kolonnen skriver `app.ai_chunk` om én gang under en eksklusiv lås, slik at jordingsforespørsler venter på den; ingenting annet berører den tabellen.

På en tjener uten pgvector logger 0264 et varsel og endrer ingenting, og gjenfinning forblir eksakt. Med en pgvector eldre enn 0.8 bygges kolonnen og indeksen men gjenfinning forblir eksakt til utvidelsen oppgraderes (`alter extension vector update`), fordi filtrerte HNSW-skanninger trenger 0.8s iterative skanninger. For å aktivere den senere på en tjener uten den, installer utvidelsen, kjør oppstarten igjen (eller `create extension vector` som superbruker), deretter som `quire_migrator`:

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

Den er idempotent og returnerer `enabled` eller `unavailable`. Kjør den på hver dedikerte tenantdatabase også.

## Rulle tilbake <!--quire:rolling-back-->

Å rulle tilbake **kode** er alltid tilgjengelig: sett `QUIRE_RELEASE` til forrige tag og `up -d` igjen. Det virker fordi skjemaet er kompatibelt i begge retninger innen en utgivelse.

Å rulle tilbake **skjema** tilbys ikke. Hva som ikke kan omgjøres, og hvordan man gjenoppretter fra det:

| Ikke reversibelt | Gjenoppretting |
| --- | --- |
| En kontraktsmigrering som fjernet en kolonne | Punkt-i-tid-gjenoppretting til før fjerningen inn i en ny database, ekstraher, flett |
| En dataendring på stedet | Det samme, deretter avstem skrivinger siden |
| Sendte webhooks og hendelser | Kompenserende hendelser, aldri sletting |
| Sendt e-post | Et menneske skriver oppfølgingen |
| Revisjonshashkjeden | Skrives aldri om; legg ved en rettelsesoppføring |

Derfor leveres en kontraktsmigrering alene: en gjenoppretting har da en ren grense.

## Sjekke oppgraderingen <!--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/nb/ops/upgrade/index.mdx
