ronments are ephemeral. Rollbacks are automated.
// src/ops/deploy-runner.ts
import { execa } from 'execa';
import { createLogger } from './logger';
const log = createLogger('deploy-runner');
interface DeployConfig {
target: 'staging' | 'production';
dryRun: boolean;
rollbackOnFailure: boolean;
}
export async function runDeployment(config: DeployConfig): Promise<void> {
log.info('Starting idempotent deployment', config);
try {
if (config.dryRun) {
await execa('npm', ['run', 'build:check']);
log.info('Dry run validation passed');
return;
}
// Idempotent build & deploy
await execa('npm', ['run', 'build']);
await execa('npm', ['run', `deploy:${config.target}`]);
log.info('Deployment successful', { target: config.target });
} catch (error) {
log.error('Deployment failed', error);
if (config.rollbackOnFailure) {
log.warn('Triggering automatic rollback');
await execa('npm', ['run', 'rollback']);
}
throw error;
}
}
Architecture rationale: The deploy runner wraps all critical path operations in a single entry point. It enforces pre-flight validation, isolates failure states, and guarantees rollback capability. This eliminates manual deployment drift and ensures the solo operator never manages state outside version control.
Step 2: Implement Cognitive Load Routing
Solo founders must separate creation, validation, and operations into distinct time blocks. Tooling enforces these boundaries. Task routing prevents context fragmentation by batching notifications, deferring non-critical alerts, and surfacing only actionable incidents.
// src/ops/cognitive-router.ts
import { createLogger } from './logger';
const log = createLogger('cognitive-router');
type AlertSeverity = 'info' | 'warning' | 'critical';
interface AlertEvent {
id: string;
severity: AlertSeverity;
message: string;
timestamp: number;
}
const BATCH_WINDOW_MS = 300_000; // 5 minutes
let pendingAlerts: AlertEvent[] = [];
export function routeAlert(alert: AlertEvent): void {
if (alert.severity === 'critical') {
log.critical('Immediate escalation required', alert);
// Trigger page/notification
return;
}
pendingAlerts.push(alert);
if (pendingAlerts.length >= 5) {
flushAlerts();
}
}
function flushAlerts(): void {
if (pendingAlerts.length === 0) return;
const batch = [...pendingAlerts];
pendingAlerts = [];
log.info('Batched operational alerts', { count: batch.length, alerts: batch });
// Route to digest channel or dashboard
}
Architecture rationale: Cognitive routing prevents alert fatigue and preserves deep work windows. Critical failures interrupt immediately; non-critical telemetry aggregates into scheduled digests. This mirrors production SRE practices but scales down to single-owner constraints.
Step 3: Config-Driven Feature Isolation
Feature flags decouple deployment from release. Solo operators ship code continuously while controlling user exposure. Configuration lives in version control, not environment variables, to maintain auditability and rollback safety.
// src/config/feature-store.ts
import { createLogger } from './logger';
const log = createLogger('feature-store');
export interface FeatureFlag {
key: string;
enabled: boolean;
rolloutPercentage?: number;
requiresAuth?: boolean;
}
const FEATURE_CONFIG: Record<string, FeatureFlag> = {
'v2-dashboard': { key: 'v2-dashboard', enabled: false, rolloutPercentage: 0 },
'ai-assistant': { key: 'ai-assistant', enabled: true, rolloutPercentage: 25, requiresAuth: true },
'export-csv': { key: 'export-csv', enabled: true, rolloutPercentage: 100 },
};
export function isFeatureActive(key: string, userId?: string): boolean {
const feature = FEATURE_CONFIG[key];
if (!feature) {
log.warn('Unknown feature flag requested', { key });
return false;
}
if (!feature.enabled) return false;
if (feature.requiresAuth && !userId) return false;
if (feature.rolloutPercentage === 100) return true;
if (feature.rolloutPercentage === 0) return false;
// Deterministic rollout based on user ID hash
const hash = userId ? simpleHash(userId) % 100 : 0;
return hash < feature.rolloutPercentage;
}
function simpleHash(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
}
Architecture rationale: Deterministic feature flag evaluation prevents race conditions and ensures consistent user experiences. Configuration lives in code to guarantee reproducibility. Rollout percentages enable safe, incremental exposure without infrastructure changes.
Step 4: Observability-First Instrumentation
Solo operators cannot debug blind systems. Structured logging, error boundaries, and health checks replace manual tracing. Every failure path logs context. Every endpoint exposes readiness and liveness probes.
// src/ops/health-check.ts
import { createLogger } from './logger';
const log = createLogger('health-check');
interface HealthStatus {
status: 'healthy' | 'degraded' | 'unhealthy';
uptime: number;
memoryUsage: number;
lastDeployment: string;
dependencies: Record<string, 'ok' | 'fail'>;
}
export function generateHealthReport(): HealthStatus {
const memUsage = process.memoryUsage().heapUsed / 1024 / 1024;
const status: HealthStatus['status'] = memUsage > 512 ? 'degraded' : 'healthy';
log.info('Health check executed', { status, memoryMB: memUsage.toFixed(2) });
return {
status,
uptime: process.uptime(),
memoryUsage: memUsage,
lastDeployment: process.env.DEPLOY_TIMESTAMP || 'unknown',
dependencies: {
database: 'ok',
cache: 'ok',
storage: 'ok',
},
};
}
Architecture rationale: Health endpoints enable automated load balancers, uptime monitors, and incident detection to function without human intervention. Memory and dependency tracking surface degradation before user impact. Structured logs ensure single-owner debugging requires zero guesswork.
Pitfall Guide
-
Over-engineering the stack
Microservices, service meshes, and custom orchestration multiply operational surface area. Solo founders should run a modular monolith or edge-function architecture until traffic demands separation. Premature distribution increases debugging complexity and deployment latency.
-
Treating monitoring as optional
Silent failures compound into outages. Every critical path must emit metrics, logs, and traces. Absence of observability forces reactive debugging, which destroys iteration velocity. Implement structured logging and uptime probes before shipping to production.
-
Manual environment provisioning
Drift between development, staging, and production causes deployment failures. Infrastructure must be declarative. Use IaC or platform-managed environments. Never configure production manually. Idempotent provisioning guarantees reproducibility.
-
Context fragmentation across tools
Scattering tasks across email, chat, project boards, and terminal windows destroys focus. Consolidate operational routing into a single digest channel. Batch non-critical notifications. Enforce time-blocked creation windows. Tooling should protect attention, not consume it.
-
Skipping runbooks and documentation
Solo operators forget their own decisions within weeks. Architecture diagrams, deployment runbooks, and incident playbooks must live in the repository. Treat documentation as code. Review it during pull requests. Missing runbooks guarantee prolonged recovery during incidents.
-
Ignoring operational debt
Manual scripts, hardcoded secrets, and ad-hoc fixes accumulate silently. Schedule monthly operational reviews. Refactor automation, rotate credentials, and prune unused services. Operational debt compounds faster than technical debt and directly impacts runway.
-
Optimizing for scale before stability
Caching layers, CDN rules, and database sharding add complexity without solving core instability. Stabilize error boundaries, automate rollbacks, and instrument observability first. Scale optimizations only after the system demonstrates consistent healthy state under load.
Best practices from production: Automate the critical path before writing business logic. Design for single-owner debugging. Prefer idempotent operations over stateful ones. Treat configuration as version-controlled artifacts. Enforce cognitive boundaries through tooling, not willpower.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| MVP Launch (<1k users) | Modular monolith + edge functions | Minimizes operational overhead, accelerates iteration | Low infrastructure, high dev velocity |
| Scaling to 10k users | Split read/write paths + cache layer | Reduces database contention, improves latency | Moderate infra cost, requires caching strategy |
| Handling production incident | Automated rollback + structured logs | Restores service quickly, isolates root cause | Zero manual cost, prevents revenue loss |
| Adding first engineer | Documented runbooks + feature flag isolation | Enables safe handoff, reduces onboarding friction | Low tooling cost, prevents knowledge silos |
Configuration Template
// solo-os.config.ts
import type { DeployConfig } from './src/ops/deploy-runner';
import type { FeatureFlag } from './src/config/feature-store';
export const DEPLOY_CONFIG: DeployConfig = {
target: 'production',
dryRun: false,
rollbackOnFailure: true,
};
export const FEATURE_FLAGS: Record<string, FeatureFlag> = {
'v2-dashboard': { key: 'v2-dashboard', enabled: false, rolloutPercentage: 0 },
'ai-assistant': { key: 'ai-assistant', enabled: true, rolloutPercentage: 25, requiresAuth: true },
'export-csv': { key: 'export-csv', enabled: true, rolloutPercentage: 100 },
};
export const COGNITIVE_ROUTING = {
batchWindowMs: 300_000,
maxBatchSize: 5,
criticalEscalation: true,
digestChannel: 'ops-digest',
};
export const HEALTH_CHECK = {
memoryThresholdMB: 512,
dependencyTimeoutMs: 2000,
exposeMetrics: true,
};
export default {
deploy: DEPLOY_CONFIG,
features: FEATURE_FLAGS,
routing: COGNITIVE_ROUTING,
health: HEALTH_CHECK,
};
Quick Start Guide
- Initialize the repository: Clone the solo OS template, install dependencies, and verify environment parity with
npm run env:verify.
- Apply configuration: Copy
solo-os.config.ts to your project root, adjust rollout percentages and thresholds, and commit to version control.
- Deploy with idempotency: Run
npm run deploy:staging to validate the pipeline. Confirm automated rollback triggers on failure simulation.
- Verify observability: Access
/health endpoint, confirm structured logs emit in CI, and validate alert routing in staging.
- Ship to production: Execute
npm run deploy:production. Monitor digest channel for batched telemetry. Close the loop by documenting the deployment in the runbook repository.