Daemon Guide
The mik daemon is a background process that manages WASM instances and provides embedded services (KV, SQL, Storage, Cron). It exposes a REST API for programmatic control.
Operating Modes
Section titled “Operating Modes”mik supports three operating modes, each adding more capabilities:
| Mode | Command | Services | Use Case |
|---|---|---|---|
| Direct | mik run | None | Quick testing |
| Daemon | mik dev or mik run --detach | Embedded (SQLite, KV, Storage, Cron) | Dev, small deployments |
| Sidecar | Handler + mikcar | Production (Postgres, Redis, S3) | Scale, multi-node |
Direct Mode
Section titled “Direct Mode”Run a handler in the foreground with no additional services:
mik run # Serves modules/ on port 3000mik run my-handler.wasm # Serves single componentHandlers can only make outbound HTTP calls. No database, no cron, no storage.
Daemon Mode (this guide)
Section titled “Daemon Mode (this guide)”The daemon provides a mini-sidecar with embedded services:
Handlers call http://localhost:9919/kv/..., /sql/..., etc.
Sidecar Mode (mikcar)
Section titled “Sidecar Mode (mikcar)”For production at scale, use mikcar instead:
Same HTTP API, different backends. Your handler code doesn’t change - just swap the sidecar.
Quick Start
Section titled “Quick Start”The daemon is auto-managed - it starts automatically when needed and stops when the last instance exits.
# Development mode (watch + services, foreground)mik dev
# Or run as background instance (auto-starts daemon)mik run --detach --name myapp --port 3000
# Check running instancesmik ps
# View logsmik logs myapp -f
# Stop the instance (daemon auto-exits when last instance stops)mik stop myappAuthentication
Section titled “Authentication”API key authentication is optional. Set MIK_API_KEY before starting:
# Enable authentication (set before mik dev or mik run --detach)export MIK_API_KEY="your-secret-key"mik dev
# All requests must include the API key headercurl -H "X-API-Key: your-secret-key" http://localhost:9919/instancesExempt endpoints (always accessible for monitoring):
GET /healthGET /metrics
Daemon Configuration
Section titled “Daemon Configuration”The daemon can be configured globally via ~/.mik/daemon.toml. This configuration is separate from per-project mik.toml files and applies to the daemon regardless of which project is running.
Configuration File
Section titled “Configuration File”Create ~/.mik/daemon.toml:
[daemon]port = 9919 # Daemon API port (default: 9919)max_auto_restarts = 10 # Max auto-restarts before giving up (default: 10)health_check_interval_secs = 10 # Health check interval (default: 10)
[services]kv_enabled = true # Enable KV service (default: true)sql_enabled = true # Enable SQL service (default: true)storage_enabled = true # Enable Storage service (default: true)If the file doesn’t exist, all defaults are used (all services enabled, port 9919).
| Field | Type | Default | Description |
|---|---|---|---|
daemon.port | number | 9919 | Daemon API port |
daemon.max_auto_restarts | number | 10 | Max auto-restart attempts before giving up |
daemon.health_check_interval_secs | number | 10 | Interval between health checks (seconds) |
services.kv_enabled | boolean | true | Enable KV service |
services.sql_enabled | boolean | true | Enable SQL service |
services.storage_enabled | boolean | true | Enable Storage service |
Disabling Services
Section titled “Disabling Services”For security-conscious deployments, you can disable services you don’t need:
[daemon]port = 9919
[services]kv_enabled = truesql_enabled = false # Disable SQL - reduces attack surfacestorage_enabled = false # Disable StorageWhen a service is disabled:
- The service is not initialized at startup (saves resources)
- Requests to disabled service endpoints return 503 Service Unavailable:
{"error": "SQL service is disabled. Enable it in ~/.mik/daemon.toml"}Startup Output
Section titled “Startup Output”When the daemon starts, it shows which services are enabled:
Starting mik daemon on port 9919...API endpoint: http://127.0.0.1:9919
Endpoints: Instances: /instances, /instances/:name, ... Cron: /cron, /cron/:name, ... Services: /kv, /storage System: /health, /version, /metrics
Disabled services: - SQL service Edit ~/.mik/daemon.toml to enable themCLI Port Override
Section titled “CLI Port Override”The CLI --port flag overrides the config file port:
# Uses config port (or default 9919)mik daemon
# Overrides config - uses port 8080mik daemon --port 8080Use Cases
Section titled “Use Cases”| Scenario | Configuration |
|---|---|
| Full development | All services enabled (default) |
| Stateless handlers | Disable SQL, Storage - KV only for sessions |
| Read-only deployment | Disable all services |
| Docker/container | Set consistent port across environments |
| High availability | Increase max_auto_restarts, decrease health_check_interval_secs |
| Debug/testing | Disable auto-restart with max_auto_restarts = 0 |
Instance Management
Section titled “Instance Management”Manage WASM instances via REST API or CLI.
REST API
Section titled “REST API”# List all instancesGET /instances
# Start a new instancePOST /instancesContent-Type: application/json{ "name": "myapp", "port": 3000, "config": "/path/to/mik.toml", "auto_restart": true}
# Get instance detailsGET /instances/{name}
# Stop an instanceDELETE /instances/{name}
# Restart an instancePOST /instances/{name}/restart
# Get instance logsGET /instances/{name}/logs?lines=100CLI Commands
Section titled “CLI Commands”mik dev [--port PORT] [--no-services] # Development with watch + servicesmik run --detach [--name NAME] [--port PORT] # Background instancemik stop [NAME] # Stop instancemik ps # List instancesmik logs [NAME] [-f] [-n LINES] # View logsExample: Start and Monitor
Section titled “Example: Start and Monitor”# Start as background instancemik run --detach --name myapp --port 3000
# Check statuscurl http://localhost:9919/instances/myapp
# Response:{ "name": "myapp", "port": 3000, "status": "running", "pid": 12345, "uptime": "2h 15m", "config": "/home/user/myapp/mik.toml"}KV Store
Section titled “KV Store”Redis-like key-value storage backed by redb. Supports TTL for automatic expiration.
# Set a value (with optional TTL in seconds)PUT /kv/{key}Content-Type: application/json{"value": "hello world", "ttl": 3600}
# Get a valueGET /kv/{key}# Response: {"key": "mykey", "value": "hello world"}
# Delete a keyDELETE /kv/{key}
# List keys (with optional prefix filter)GET /kv?prefix=user:# Response: {"keys": ["user:1", "user:2", "user:3"]}Example: Session Storage
Section titled “Example: Session Storage”# Store session with 1 hour TTLcurl -X PUT http://localhost:9919/kv/session:abc123 \ -H "Content-Type: application/json" \ -d '{"value": "{\"user_id\": 42, \"role\": \"admin\"}", "ttl": 3600}'
# Retrieve sessioncurl http://localhost:9919/kv/session:abc123
# List all sessionscurl "http://localhost:9919/kv?prefix=session:"SQL Database
Section titled “SQL Database”Embedded SQLite database with full SQL support. Foreign keys are enabled by default.
# Execute DDL/DML (CREATE, INSERT, UPDATE, DELETE)POST /sql/executeContent-Type: application/json{"sql": "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)"}
# Query data (SELECT)POST /sql/queryContent-Type: application/json{"sql": "SELECT * FROM users WHERE id = ?", "params": [1]}
# Response:{ "columns": ["id", "name"], "rows": [{"id": 1, "name": "Alice"}], "rows_affected": 0}Batch Operations (Atomic)
Section titled “Batch Operations (Atomic)”Batch executes multiple statements in a single transaction. If any statement fails, all changes are rolled back.
POST /sql/batchContent-Type: application/json{ "statements": [ {"sql": "INSERT INTO users (name) VALUES (?)", "params": ["Alice"]}, {"sql": "INSERT INTO users (name) VALUES (?)", "params": ["Bob"]}, {"sql": "UPDATE users SET name = ? WHERE id = ?", "params": ["Charlie", 1]} ]}
# Response:{ "results": [ {"rows_affected": 1}, {"rows_affected": 1}, {"rows_affected": 1} ], "total_affected": 3}Example: Create Schema
Section titled “Example: Create Schema”# Create tablescurl -X POST http://localhost:9919/sql/execute \ -H "Content-Type: application/json" \ -d '{"sql": "CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY, title TEXT, user_id INTEGER REFERENCES users(id))"}'
# Insert with foreign keycurl -X POST http://localhost:9919/sql/execute \ -H "Content-Type: application/json" \ -d '{"sql": "INSERT INTO posts (title, user_id) VALUES (?, ?)", "params": ["Hello World", 1]}'
# Query with joincurl -X POST http://localhost:9919/sql/query \ -H "Content-Type: application/json" \ -d '{"sql": "SELECT p.title, u.name FROM posts p JOIN users u ON p.user_id = u.id"}'Object Storage
Section titled “Object Storage”S3-like object storage backed by the filesystem. Supports any file type with automatic content-type detection.
# Upload a filePUT /storage/{path}Content-Type: application/octet-stream<binary data>
# Download a fileGET /storage/{path}
# Delete a fileDELETE /storage/{path}
# Get metadata (size, content-type, timestamps)HEAD /storage/{path}
# List objects (with optional prefix)GET /storage?prefix=images/Example: File Upload
Section titled “Example: File Upload”# Upload an imagecurl -X PUT http://localhost:9919/storage/images/logo.png \ -H "Content-Type: image/png" \ --data-binary @logo.png
# Get metadatacurl -I http://localhost:9919/storage/images/logo.png# Headers: Content-Type, Content-Length, Last-Modified, ETag
# List all imagescurl "http://localhost:9919/storage?prefix=images/"# Response: {"objects": [{"path": "images/logo.png", "size": 12345, ...}]}
# Downloadcurl http://localhost:9919/storage/images/logo.png -o downloaded.pngCron Scheduler
Section titled “Cron Scheduler”Schedule recurring jobs using cron expressions. Jobs call WASM module endpoints via HTTP.
Endpoints
Section titled “Endpoints”# List all jobsGET /cron
# Create a new jobPOST /cronContent-Type: application/json{ "name": "cleanup", "cron": "0 0 * * * * *", "module": "cleanup.wasm", "method": "POST", "path": "/run", "port": 3000, "enabled": true}
# Get job detailsGET /cron/{name}
# Update job (pause/resume)PATCH /cron/{name}Content-Type: application/json{"enabled": false}
# Delete a jobDELETE /cron/{name}
# Manually trigger a jobPOST /cron/{name}/trigger
# Get execution historyGET /cron/{name}/historyCron Expression Format
Section titled “Cron Expression Format”Uses 7-field format: sec min hour day month weekday year
0 0 0 * * * * # Daily at midnight0 */5 * * * * * # Every 5 minutes0 0 12 * * MON * # Every Monday at noon0 30 9 1 * * * # 9:30 AM on the 1st of each monthExample: Create a Cleanup Job
Section titled “Example: Create a Cleanup Job”# Create job that runs every hourcurl -X POST http://localhost:9919/cron \ -H "Content-Type: application/json" \ -d '{ "name": "hourly-cleanup", "cron": "0 0 * * * * *", "module": "cleanup.wasm", "method": "POST", "path": "/cleanup", "port": 3000, "enabled": true }'
# Pause the jobcurl -X PATCH http://localhost:9919/cron/hourly-cleanup \ -H "Content-Type: application/json" \ -d '{"enabled": false}'
# Trigger manually for testingcurl -X POST http://localhost:9919/cron/hourly-cleanup/trigger
# Check execution historycurl http://localhost:9919/cron/hourly-cleanup/history# Response:{ "job_name": "hourly-cleanup", "executions": [ { "id": "abc-123", "started_at": "2025-01-15T10:00:00Z", "completed_at": "2025-01-15T10:00:01Z", "duration_ms": 1250, "success": true, "manual": true } ]}Jobs from mik.toml
Section titled “Jobs from mik.toml”Jobs defined in mik.toml are automatically registered when an instance starts:
[[schedules]]name = "daily-report"cron = "0 0 8 * * * *"module = "reports.wasm"method = "POST"path = "/generate"Prometheus Metrics
Section titled “Prometheus Metrics”GET /metricsAvailable metrics:
| Metric | Description |
|---|---|
mik_http_requests_total | Total HTTP requests by path and status |
mik_http_request_duration_seconds | Request latency histogram |
mik_instance_count | Running/stopped/crashed instances |
mik_instance_uptime_seconds | Instance uptime |
mik_kv_operations_total | KV operations by type |
mik_sql_queries_total | SQL queries by type |
mik_storage_operations_total | Storage operations by type |
mik_cron_executions_total | Cron job executions |
mik_cron_execution_duration_seconds | Cron job duration |
System Endpoints
Section titled “System Endpoints”# Health check (always returns 200 if daemon is running)GET /health# Response: {"status": "healthy", "uptime": "running"}
# Version infoGET /version# Response: {"version": "0.1.0", "build": "release"}Architecture
Section titled “Architecture”Summary
Section titled “Summary”The daemon is a mini-sidecar - embedded services for development and small deployments. For production at scale, swap to mikcar with the same API but real infrastructure backends.
See Operating Modes for the full comparison.