---
title: "Actualizar sin tiempo de inactividad"
description: "Actualiza Quire autoalojado sin tiempo de inactividad."
image: "https://docs.quirelms.com/og.png"
---

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

# Actualizar sin tiempo de inactividad

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

Las reglas están en la sección 7 de `docs/architecture/23-ops.md` y en la sección 4.1 de `docs/architecture/07-data.md`. Este es el procedimiento.

## La garantía que lo hace seguro <!--quire:the-guarantee-that-makes-it-safe-->

**La versión R funciona correctamente con el esquema R y con el esquema R menos uno.** Cada cambio de esquema se divide en ampliación, transición y contracción:

1. **Ampliación**: agrega la nueva columna, tabla o índice. El código anterior la ignora.
2. **Transición**, durante al menos una versión: el código nuevo escribe en ambos formatos y lee el nuevo; una tarea reanudable completa las filas anteriores.
3. **Contracción**: elimina el formato anterior en una versión posterior y por separado.

Así, durante una actualización gradual, los procesos anteriores y nuevos pueden compartir una base de datos. No hay migraciones inversas: una migración que eliminó una columna hace una hora no puede recuperar las filas que se escribieron durante esa hora.

El trabajo de CI `schema-compat` verifica esta garantía en cada versión: ejecuta las pruebas de la versión anterior contra el esquema nuevo.

## Antes de empezar <!--quire:before-you-start-->

1. Lee las notas de la versión. Si una versión necesita una ventana de mantenimiento, se indica el tiempo estimado; hay como máximo una por versión.
2. Ejecuta el simulacro de restauración o confirma que terminó correctamente con esta versión ([backup-restore.md](/es-419/ops/backup-restore/)). Si falla, no se puede continuar con la actualización.
3. Crea un respaldo base: `docker compose -f docker/compose.yaml --profile backup run --rm backup`.

## Docker Compose, un solo 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
```

El orden es intencional:

1. **Primero, migra**, mientras la versión anterior sigue atendiendo tráfico. Las migraciones de ampliación son invisibles para ella.
2. **Luego, la capa web.** Al recibir SIGTERM, cada proceso web cambia `/readyz` a `draining`, termina las solicitudes en curso en un máximo de 30 segundos, cierra los flujos con una indicación para volver a conectarse y sale. `stop_grace_period` es de 40 segundos para que Compose no interrumpa un apagado correcto.
3. **Al final, los workers**, para que se genere el formato de evento más nuevo antes de que lo espere el consumidor nuevo. Los workers dejan de obtener tareas de inmediato y tienen 120 segundos para terminarlas; si una tarea no acaba, otro proceso la vuelve a obtener. Es seguro porque todas las tareas son idempotentes. El scheduler transfiere el liderazgo en el siguiente turno.

En un solo host, Compose reemplaza cada contenedor por turnos, así que hay una interrupción breve por servicio. Para evitar cualquier interrupción, ejecuta la capa web en dos contenedores detrás de tu propio proxy (con un archivo de reemplazo que agregue un segundo servicio web sin puerto publicado) y vuelve a crearlos de uno en uno; espera a que cada uno esté saludable antes de pasar al siguiente.

## Varios hosts u orquestador <!--quire:several-hosts-or-an-orchestrator-->

Sigue el mismo orden: ejecuta una tarea de migración y luego actualiza la capa web de forma gradual, con una instancia adicional disponible y ninguna fuera de servicio; después actualiza los workers. Configura las comprobaciones de preparación en `/readyz` y de disponibilidad en `/healthz`.

Con bases de datos de tenants dedicadas, el paso `migrate` hace ambas cosas: primero migra la base de datos de control y luego cada base de datos enumerada en `ops.tenant_database`, una por una y con su propio bloqueo. Si falla una base de tenant, las demás se procesan igual. Cuando termina con todas, compara los historiales de migración y devuelve un código distinto de cero, a menos que cada base haya aplicado exactamente las migraciones de la base de control; indica cuáles están atrasadas o adelantadas. El mismo comando instala las tablas de la cola en cada base porque el worker consume ahí las tareas del tenant fijado.

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```

Se accede a cada base dedicada mediante el nombre con el que está registrada. Una base registrada como `env:QUIRE_DB_NORTHWIND_URL` necesita:

| Variable | Se usa para |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Rol de aplicación, para la capa web y el worker |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | Rol de migración, para este comando y los traslados |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | Opcional: vuelve a ejecutar la inicialización (roles, esquemas y funciones auxiliares) antes de migrar |

Si una base registrada no tiene una conexión `_MIGRATOR`, se informa como error; nunca se omite. La capa web puede actualizarse cuando termine la base de control. Si una base de tenant lleva una hora atrasada, se genera una advertencia; si lleva un día, se envía una alerta de prioridad alta.

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

Desde la migración 0264, el corpus de fundamentación usa un índice pgvector HNSW cuando el servidor tiene la extensión; el servicio `postgres` de Compose se compila con ella (`docker/postgres.Dockerfile`). El primer `migrate` después de cambiar las imágenes crea la extensión mediante la inicialización de superusuario y luego la migración 0264 agrega una columna vectorial generada y crea el índice. Al agregar la columna, se reescribe `app.ai_chunk` una vez con un bloqueo exclusivo, así que las solicitudes de fundamentación esperan; ninguna otra operación toca esa tabla.

En un servidor sin pgvector, 0264 muestra un aviso y no cambia nada; la recuperación sigue siendo exacta. Con una versión de pgvector anterior a 0.8, se crean la columna y el índice, pero la recuperación sigue siendo exacta hasta actualizar la extensión (`alter extension vector update`), porque los recorridos HNSW filtrados requieren los recorridos iterativos de la versión 0.8. Para activarla más adelante en un servidor que no la tenga, instala la extensión, vuelve a ejecutar la inicialización (o `create extension vector` como superusuario) y después ejecuta, como `quire_migrator`:

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

Es idempotente y devuelve `enabled` o `unavailable`. Ejecútala también en cada base de datos de tenant dedicada.

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

Siempre se puede revertir el **código**: configura `QUIRE_RELEASE` con la etiqueta anterior y vuelve a ejecutar `up -d`. Funciona porque el esquema es compatible en ambos sentidos dentro de una versión.

No se permite revertir el **esquema**. Estas son las acciones irreversibles y cómo recuperarse:

| Acción irreversible | Recuperación |
| --- | --- |
| Una migración de contracción que eliminó una columna | Restaurar a un momento anterior a la eliminación en una base nueva; después, extraer y combinar los datos |
| Un cambio de datos en el lugar | Lo mismo y luego conciliar las escrituras posteriores |
| Webhooks y eventos enviados | Eventos compensatorios, nunca se eliminan |
| Correos enviados | Una persona redacta el mensaje de seguimiento |
| Cadena hash de auditoría | Nunca se reescribe; se agrega una entrada de corrección |

Por eso las migraciones de contracción se despliegan solas: así la restauración tiene un límite claro.

## Verificar la actualización <!--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/es-419/ops/upgrade/index.mdx
