Skip to content

Maintenance Mode

CruzJS provides a maintenance mode that returns a 503 response to all requests, with an optional bypass token for admin access during downtime.

Register the MaintenanceModule in your application:

import { MaintenanceModule } from '@cruzjs/core/maintenance';
export default createCruzApp({
modules: [MaintenanceModule],
});
trpc.maintenance.enable.useMutation().mutate({
message: 'We are upgrading our systems. Back in 30 minutes.',
});
import { Injectable, Inject } from '@cruzjs/core/di';
import { MaintenanceService } from '@cruzjs/core/maintenance';
@Injectable()
export class DeployService {
constructor(
@Inject(MaintenanceService) private readonly maintenance: MaintenanceService,
) {}
async startMigration() {
await this.maintenance.enable('Database migration in progress.');
try {
await this.runMigration();
} finally {
await this.maintenance.disable();
}
}
}

When maintenance mode is active:

  • HTML requests receive a 503 response with a maintenance page displaying the custom message
  • API/JSON requests receive a 503 JSON response: { "error": "Service unavailable", "message": "..." }
  • tRPC requests receive a 503 with the maintenance message

Set the MAINTENANCE_BYPASS_TOKEN environment variable to allow admin access during maintenance:

Terminal window
MAINTENANCE_BYPASS_TOKEN=my-secret-bypass-token

Include the token in the X-Maintenance-Bypass header to skip the maintenance check:

Terminal window
curl -H "X-Maintenance-Bypass: my-secret-bypass-token" https://yourapp.com/admin
MethodReturnsDescription
enable(message?)Promise<void>Activate maintenance mode with optional message
disable()Promise<void>Deactivate maintenance mode
getStatus()Promise<{ enabled, message }>Get current maintenance status
isEnabled()Promise<boolean>Check if maintenance mode is active
ProcedureTypeAuthDescription
maintenance.getStatusqueryPublicCheck if maintenance mode is active
maintenance.enablemutationAdminEnable maintenance mode
maintenance.disablemutationAdminDisable maintenance mode

The getStatus procedure is public so that client apps can show a maintenance banner or redirect to a maintenance page.

PlatformBackendNotes
CloudflareKVMaintenance state stored in KV namespace
Docker / ContainersIn-memoryState lives in application memory
DevelopmentIn-memoryResets on server restart
function MaintenanceBanner() {
const { data } = trpc.maintenance.getStatus.useQuery(undefined, {
refetchInterval: 30_000, // Check every 30 seconds
});
if (!data?.enabled) return null;
return (
<div className="bg-yellow-50 border-yellow-200 border p-4 text-center">
<p className="font-medium">
{data.message || 'The site is undergoing maintenance.'}
</p>
</div>
);
}