-
Notifications
You must be signed in to change notification settings - Fork 0
Operations Operation Mode
ReadyStackGo uses Operation Modes to manage the lifecycle state of deployments. This allows you to put stacks into maintenance, track migrations, and handle failures gracefully.
Operation Mode is distinct from health status:
- Health Status (Healthy/Degraded/Unhealthy) = Technical state reported by containers
- Operation Mode (Normal/Maintenance/Migrating/etc.) = Operational state set by RSGO
RSGO is the source of truth for operation mode, while containers report their technical state.
| Mode | Icon | Description |
|---|---|---|
| Normal | 🟢 | Standard operation, all services should be running |
| Maintenance | 🔧 | Planned maintenance, services may be stopped |
| Migrating | 🔄 | Upgrade/migration in progress |
| Failed | 🔴 | Migration or operation failed, requires intervention |
| Stopped | ⏹️ | Stack intentionally stopped |
Maintenance mode allows you to temporarily stop a stack for updates, backups, or configuration changes.
When entering maintenance mode:
- Operation mode changes to
Maintenance - All stack containers are automatically stopped
- Health status reflects the expected down state
- UI shows maintenance indicator
Normal → Maintenance
│
└── All containers stopped (via Docker API)
Maintenance → Normal
│
└── All containers started (via Docker API)
Some containers (like databases) should continue running during maintenance. Use the rsgo.maintenance label:
services:
postgres:
image: postgres:16
labels:
rsgo.stack: my-app
rsgo.maintenance: ignore # ← Won't be stopped during maintenance
api:
image: myapp/api:latest
labels:
rsgo.stack: my-app
# No rsgo.maintenance label = will be stoppedContainers with rsgo.maintenance: ignore are:
- Not stopped when entering maintenance mode
- Not started when exiting maintenance mode (already running)
- Database migrations: Stop app containers, run migrations, restart
- Backup windows: Stop services during backup
- Configuration updates: Safe config changes without traffic
Migration mode tracks upgrades and version transitions.
When deploying a new version:
- Operation mode changes to
Migrating -
TargetVersionis set (e.g., "2.0.0") - Current version is preserved
- Health shows "Migrating" status
Normal (v1.0)
│
▼
Migrating (target: v2.0)
│
├── Success ──► Normal (v2.0)
│
└── Failure ──► Failed (rollback possible)
On successful migration:
- Operation mode returns to
Normal - Stack version updated to target version
- Health monitoring resumes normal checks
Failed mode indicates a problem requiring manual intervention.
- Migration failed during execution
- Deployment error
- Manual override
To recover from failed state:
- Investigate the failure cause (logs, health history)
- Fix the underlying issue
- Use "Recover" action in UI
- Or re-deploy with corrected configuration
Stopped mode indicates an intentionally stopped stack.
- Different from failure (planned state)
- All containers should be stopped
- No automatic restart attempts
PUT /api/deployments/{deploymentId}/operation-mode
Content-Type: application/json
{
"newMode": "Maintenance",
"reason": "Scheduled maintenance window"
}Not all transitions are allowed:
| From | To | Allowed |
|---|---|---|
| Normal | Maintenance | ✅ |
| Normal | Migrating | ✅ (via deploy) |
| Maintenance | Normal | ✅ |
| Migrating | Normal | ✅ (on success) |
| Migrating | Failed | ✅ (on failure) |
| Failed | Normal | ✅ (via recover) |
| Stopped | Normal | ✅ (via start) |
Operation mode is shown alongside health:
┌────────────────────────────────────────────┐
│ Stack │ Health │ Mode │
├────────────────────────────────────────────┤
│ Production │ 🟢 │ Normal │
│ Staging │ 🟡 │ 🔧 Maintenance │
│ Development │ ⚪ │ 🔄 Migrating │
└────────────────────────────────────────────┘
The detail view shows:
- Current operation mode with visual indicator
- Mode history (when mode changed, by whom)
- Available actions based on current mode
Available actions depend on current mode:
| Mode | Available Actions |
|---|---|
| Normal | Enter Maintenance, Stop |
| Maintenance | Exit Maintenance |
| Migrating | (Wait for completion) |
| Failed | Recover, Redeploy |
| Stopped | Start |
Operation mode changes trigger immediate SignalR notifications:
- UI updates without refresh
- All connected clients see the change
- Health widget reflects new state
Maintenance Observers allow external systems to trigger maintenance mode automatically. Instead of manually switching modes, RSGO monitors external state and synchronizes the operation mode accordingly.
External System RSGO Observer Stack
│ │ │
│ State changes │ │
│ (DB property=1) │ │
│ ─────────────────────► │ │
│ │ Enter Maintenance │
│ │ ──────────────────►│
│ │ │ Containers stopped
│ │ │
│ State restored │ │
│ (DB property=0) │ │
│ ─────────────────────► │ │
│ │ Exit Maintenance │
│ │ ──────────────────►│
│ │ │ Containers started
Monitors a SQL Server Extended Property and triggers maintenance mode based on its value.
Use Case: Legacy applications or backend systems set a database property during their own maintenance. RSGO automatically puts the dependent stack into maintenance mode.
Manifest Configuration:
metadata:
name: Legacy Integration Stack
productVersion: "1.0.0"
variables:
DB_CONNECTION:
type: SqlServerConnectionString
label: Database Connection
required: true
maintenanceObserver:
type: sqlExtendedProperty
connectionString: ${DB_CONNECTION} # Direct variable reference
# OR: connectionName: DB_CONNECTION # Reference by variable name
propertyName: app.MaintenanceMode
maintenanceValue: "1" # When property = 1 → enter maintenance
normalValue: "0" # When property = 0 → exit maintenance
pollingInterval: 30s # Check every 30 seconds
services:
api:
image: myapp/api:latest
# Will be stopped automatically when app.MaintenanceMode = 1Connection Options:
| Property | Description |
|---|---|
connectionString |
Direct connection string or variable substitution (${VAR}) |
connectionName |
Name of a defined variable (e.g., DB_CONNECTION, LEGACY_DB) |
Using connectionName is recommended when you already have a connection string variable defined in your manifest - it avoids duplication and ensures consistency.
Extended Property Example:
-- Set maintenance mode ON
EXEC sp_addextendedproperty
@name = N'app.MaintenanceMode',
@value = N'1';
-- Set maintenance mode OFF
EXEC sp_updateextendedproperty
@name = N'app.MaintenanceMode',
@value = N'0';
-- Query current value
SELECT value
FROM sys.extended_properties
WHERE name = 'app.MaintenanceMode';Executes a custom SQL query and triggers maintenance based on the result.
Use Case: More complex conditions, multiple tables, or non-Extended Property sources.
Manifest Configuration:
maintenanceObserver:
type: sqlQuery
connectionName: PERSISTENCE_DB # Reference existing variable
# OR: connectionString: ${PERSISTENCE_DB}
query: |
SELECT CASE
WHEN EXISTS (SELECT 1 FROM SystemStatus WHERE Status = 'Maintenance')
THEN 'maintenance'
ELSE 'normal'
END AS Mode
maintenanceValue: "maintenance"
normalValue: "normal"
pollingInterval: 60sMonitors an HTTP endpoint and triggers maintenance based on the response.
Use Case: External maintenance APIs, status pages, or service health endpoints.
Manifest Configuration:
maintenanceObserver:
type: http
url: https://status.example.com/api/maintenance
method: GET
headers:
Authorization: Bearer ${STATUS_TOKEN}
jsonPath: "$.maintenanceMode" # Extract value from JSON response
maintenanceValue: "true"
normalValue: "false"
pollingInterval: 30s
timeout: 10sMonitors a file for existence or content changes.
Use Case: Legacy systems that create marker files during maintenance.
Manifest Configuration:
maintenanceObserver:
type: file
path: /var/maintenance/maintenance.flag
mode: exists # 'exists' or 'content'
# mode: exists → file exists = maintenance, file absent = normal
# mode: content → compare file content with maintenanceValue/normalValue
pollingInterval: 10s| Property | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Observer type: sqlExtendedProperty, sqlQuery, http, file
|
pollingInterval |
string | No | How often to check (default: 30s) |
timeout |
string | No | Timeout for each check (default: 10s) |
maintenanceValue |
string | Yes | Value that triggers maintenance mode |
normalValue |
string | Yes | Value that exits maintenance mode |
enabled |
boolean | No | Enable/disable observer (default: true) |
Type-specific properties:
| Type | Property | Description |
|---|---|---|
sqlExtendedProperty |
connectionString |
SQL Server connection string (supports ${VAR} syntax) |
sqlExtendedProperty |
connectionName |
Name of a defined variable (alternative to connectionString) |
sqlExtendedProperty |
propertyName |
Name of the Extended Property |
sqlQuery |
connectionString |
SQL Server connection string (supports ${VAR} syntax) |
sqlQuery |
connectionName |
Name of a defined variable (alternative to connectionString) |
sqlQuery |
query |
SQL query returning single value |
http |
url |
HTTP endpoint URL |
http |
method |
HTTP method (GET, POST) |
http |
headers |
Request headers |
http |
jsonPath |
JSONPath to extract value from response |
file |
path |
File path to monitor |
file |
mode |
exists or content
|
Note: For SQL observers, use either
connectionStringORconnectionName, not both.connectionNameis recommended when you already have a connection string variable defined in your manifest.
Observer detects maintenanceValue
│
▼
┌─────────────────────────────────────────┐
│ RSGO logs: "Observer triggered: │
│ External maintenance detected" │
└─────────────────────────────────────────┘
│
▼
Enter Maintenance Mode (automatic)
│
▼
Containers stopped (respecting rsgo.maintenance labels)
If a user manually changes the mode while an observer is active:
| Scenario | Behavior |
|---|---|
| Observer says "maintenance", user sets "normal" | Observer wins on next poll |
| Observer says "normal", user sets "maintenance" | User wins (observer doesn't override manual) |
| Observer disabled | Manual control only |
To override the observer temporarily, disable it via API:
PUT /api/deployments/{id}/maintenance-observer
{ "enabled": false }| Failure | Behavior |
|---|---|
| Connection timeout | Log warning, retry on next poll |
| Query error | Log error, retain current state |
| Invalid response | Log error, retain current state |
| 3 consecutive failures | Log critical, send notification |
When an observer is configured, the UI shows:
┌─────────────────────────────────────────────────────┐
│ Operation Mode: 🔧 Maintenance │
│ ─────────────────────────────────────────────────── │
│ Triggered by: SQL Extended Property Observer │
│ Property: ams.MaintenanceMode = 1 │
│ Last checked: 15 seconds ago │
│ ─────────────────────────────────────────────────── │
│ [Disable Observer] [View History] │
└─────────────────────────────────────────────────────┘
Complete manifest for integrating with a legacy system's maintenance mode:
metadata:
name: Legacy Portal Integration
description: Stack synced with backend maintenance mode
productVersion: "2.0.0"
category: Enterprise
variables:
BACKEND_DB:
label: Backend Database Connection
type: SqlServerConnectionString
required: true
description: Connection to the backend database
API_PORT:
label: API Port
type: Port
default: "5000"
maintenanceObserver:
type: sqlExtendedProperty
connectionName: BACKEND_DB # Reference the variable by name
propertyName: app.MaintenanceMode
maintenanceValue: "1"
normalValue: "0"
pollingInterval: 30s
services:
portal-api:
image: mycompany/portal-api:latest
ports:
- "${API_PORT}:5000"
environment:
ConnectionStrings__Backend: ${BACKEND_DB}
# Stopped when app.MaintenanceMode = 1
portal-worker:
image: mycompany/portal-worker:latest
environment:
ConnectionStrings__Backend: ${BACKEND_DB}
# Stopped when app.MaintenanceMode = 1
redis:
image: redis:7
labels:
rsgo.maintenance: ignore # Keeps running during maintenanceWorkflow:
- Admin starts maintenance in the backend system
- Backend sets
app.MaintenanceMode = 1on database - RSGO Observer detects the change within 30 seconds
- RSGO enters maintenance mode, stops
portal-apiandportal-worker - Redis keeps running (has
rsgo.maintenance: ignore) - Admin completes maintenance, sets
app.MaintenanceMode = 0 - RSGO Observer detects the change
- RSGO exits maintenance mode, starts containers
- Stack is fully operational again
- Plan maintenance windows: Communicate with users before entering maintenance
-
Use labels wisely: Mark critical infrastructure containers with
rsgo.maintenance: ignore - Monitor migrations: Watch migration progress in real-time
- Document failures: Record failure reasons for post-mortem analysis
- Test recovery: Verify your recovery procedures before production issues
- Configure observers for legacy systems: Let external systems control maintenance automatically
- Set appropriate polling intervals: Balance responsiveness vs. resource usage
# 1. Notify users
# 2. Enter maintenance mode
PUT /api/deployments/{id}/operation-mode
{ "newMode": "Maintenance", "reason": "Weekly backup" }
# 3. Perform maintenance tasks
# (Databases still running if labeled with rsgo.maintenance: ignore)
# 4. Exit maintenance mode
PUT /api/deployments/{id}/operation-mode
{ "newMode": "Normal" }
# 5. Verify health
GET /api/deployments/{id}/health- Health Monitoring - Understanding health status
- Deployment Engine - How deployments work
- Container Lifecycle - Container management
Getting Started
Architecture
Configuration
Security
Setup Wizard
Development
Operations
CI/CD
Reference
- Roadmap
- API Reference
- Configuration Reference
- Manifest Schema
- Multi-Environment
- Stack Sources
- Plugin System
- Technical Specification
- Full Specification
Specifications
Release Notes