# How the OmniRoute Version Manager Handles Live Updates and Rollback

> Discover how OmniRoute's version manager ensures zero-downtime live updates and controlled rollbacks for auxiliary tools. Learn about its state persistence, orchestration, and version pinning.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: internals
- Published: 2026-08-03

---

**OmniRoute's Version Manager enables safe, zero-downtime live upgrades and controlled rollbacks for auxiliary tools through database-persisted state, process orchestration, and version pinning.**

The **OmniRoute Version Manager** is a core subsystem designed to manage the lifecycle of external tools like `9router` and `cliproxy`. According to the `diegosouzapw/OmniRoute` source code, it combines a SQLite-backed state store with runtime process management to support live version updates without server restarts and instant rollback via pinned versions.

---

## Core Architecture

The Version Manager operates through five integrated layers:

| Component | Key File | Responsibility |
|-----------|----------|----------------|
| **Database layer** | [`src/lib/db/versionManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/versionManager.ts) | Schema and CRUD operations for the `version_manager_tools` table |
| **Process manager** | [`src/lib/versionManager/processManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/versionManager/processManager.ts) | Runtime orchestration: start, stop, pin, unpin |
| **Service façade** | [`src/lib/versionManager/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/versionManager/index.ts) | Public API exports for route handlers |
| **Bootstrap controller** | [`src/lib/services/bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/bootstrap.ts) | Reads persisted state on startup to launch correct versions |
| **Tool installers** | `src/lib/services/installers/*.ts` | Binary download and version resolution logic |

The `version_manager_tools` table persists one row per tool with these critical fields:

- `installedVersion` — the currently active binary version
- `pinnedVersion` — optional override forcing a specific version
- `status` — `running`, `stopped`, or `not_installed`
- `lastStartedAt` / `lastSyncAt` — timestamps for health tracking

---

## Live Updates: Zero-Downtime Version Swaps

OmniRoute applies updates through a database-driven state machine. The server does not require restart to activate new versions.

### Step 1: API Request and Validation

Clients trigger updates via the Version Manager endpoint. The request body is validated by Zod in [`src/app/api/version-manager/request.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/version-manager/request.ts):

```ts
// Example payload for live update
{
  tool: "cliproxy",
  installedVersion: "2.1.0",
  status: "running"
}

```

### Step 2: Persist State Change

The `updateVersionManagerTool` function in [`src/lib/db/versionManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/versionManager.ts) writes the new version and status to the database row. This function is exported alongside `upsertVersionManagerTool`, `getVersionManagerTool`, and `deleteVersionManagerTool` from the same file.

### Step 3: Process Manager Reaction

The **process manager** ([`processManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/processManager.ts)) monitors the database state. When `installedVersion` changes, it:

1. Gracefully terminates the running tool process
2. Spawns the binary matching the new version
3. Records the PID and updates `lastStartedAt`

### Step 4: Health Confirmation

A background sync task ([`src/lib/services/modelSync.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/modelSync.ts)) periodically calls `updateVersionManagerTool` with fresh `lastSyncAt` timestamps, confirming the tool remains healthy.

```ts
// Direct database update for live version change
import { updateVersionManagerTool } from '@/lib/db/versionManager'

await updateVersionManagerTool('cliproxy', {
  installedVersion: '2.0.0',
  status: 'running',
  lastStartedAt: new Date().toISOString()
})

```

---

## Rollback Mechanism: Version Pinning

Rollback is controlled through the `pinnedVersion` field, which overrides any newer `installedVersion` on restart or health-check failure.

### Pinning a Version

The `pinToolVersion` function in [`processManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/processManager.ts) sets `pinnedVersion` in the database:

```ts
// Force cliproxy to run version 1.4.2 regardless of installedVersion
await updateVersionManagerTool('cliproxy', {
  pinnedVersion: '1.4.2',
  status: 'running'
})

```

### Resolver Logic in Bootstrap

When [`src/lib/services/bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/bootstrap.ts) initializes a tool, it checks `pinnedVersion` first:

1. If `pinnedVersion` exists → force that version
2. If `pinnedVersion` is `null` → use `installedVersion`
3. If neither exists → trigger installer to fetch latest

### Unpinning to Resume Auto-Upgrade

Clearing the pin restores normal upgrade behavior:

```ts
// Remove version lock
await updateVersionManagerTool('cliproxy', {
  pinnedVersion: null
})

```

### Automatic Fallback on Failure

Tool installers in [`src/lib/services/installers/cliproxy.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/installers/cliproxy.ts) and similar files implement defensive logic: if a health check fails or the binary crashes, the installer consults `pinnedVersion` (if set) or falls back to the last known good `installedVersion` recorded in the database.

---

## API Examples

### Live Update via cURL

```bash

# Upgrade cliproxy to v2.0.0 immediately

curl -X PATCH https://omniroute.example.com/api/v1/version-manager \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"tool":"cliproxy","installedVersion":"2.0.0","status":"running"}'

```

### Rollback via cURL

```bash

# Pin to older version for instant rollback

curl -X PATCH https://omniroute.example.com/api/v1/version-manager \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"tool":"cliproxy","pinnedVersion":"1.4.2"}'

```

---

## Key Source Files

| File Path | Purpose |
|-----------|---------|
| [`src/lib/db/versionManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/versionManager.ts) | Database schema and CRUD: `upsertVersionManagerTool`, `updateVersionManagerTool`, `getVersionManagerStatus` |
| [`src/lib/versionManager/processManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/versionManager/processManager.ts) | Runtime orchestration with `setToolStatus`, `pinToolVersion`, `unpinToolVersion` |
| [`src/lib/versionManager/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/versionManager/index.ts) | Public façade exporting all Version Manager functions |
| [`src/lib/services/bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/bootstrap.ts) | Startup routine reading tool state from database |
| [`src/app/api/version-manager/request.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/version-manager/request.ts) | Zod validation schemas for API requests |
| [`src/lib/services/installers/cliproxy.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/installers/cliproxy.ts) | Example installer respecting `pinnedVersion` and `installedVersion` |
| [`src/lib/services/modelSync.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/modelSync.ts) | Background health check and timestamp updates |

---

## Summary

- **Database-driven state** — The `version_manager_tools` table in [`src/lib/db/versionManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/versionManager.ts) is the single source of truth for tool versions and status
- **Zero-downtime updates** — Changing `installedVersion` triggers process manager restart without server reload
- **Controlled rollback** — The `pinnedVersion` field forces specific versions, with resolution logic in [`src/lib/services/bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/services/bootstrap.ts)
- **Health monitoring** — Background sync tasks confirm tool viability via `lastSyncAt` timestamps
- **API-first design** — All operations exposed through validated REST endpoints under `/api/v1/version-manager/`

---

## Frequently Asked Questions

### What database table stores the Version Manager state?

The `version_manager_tools` table, defined in the migration files and accessed through [`src/lib/db/versionManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/versionManager.ts), stores one row per tool with fields for `installedVersion`, `pinnedVersion`, `status`, and timing metadata.

### How does OmniRoute switch versions without restarting the server?

The process manager ([`src/lib/versionManager/processManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/versionManager/processManager.ts)) monitors database changes to `installedVersion`. When updated, it terminates the current process and spawns the new binary immediately—no server restart required.

### What happens if a tool fails health checks?

The bootstrap controller and installer scripts check `pinnedVersion` first, then fall back to the last successful `installedVersion`. This automatic recovery logic is implemented in `src/lib/services/installers/*.ts` files.

### Can I pin multiple tools to different versions simultaneously?

Yes. Each tool has its own row in `version_manager_tools` with an independent `pinnedVersion` field. Pinning one tool does not affect others.