← Back to blog

Polyglot Runbooks: Managing Mixed Technology Stacks

· 6 min read · Stew Team
runbookpolyglotdevopsmulti-language

Real infrastructure isn’t monolingual. You’ve got Bash scripts, Python tools, SQL queries, and API calls—often in the same procedure. Your runbooks should handle all of them.

This guide covers building polyglot runbooks for mixed tech stacks. For tool comparisons, see our interactive runbook tools comparison.

The Polyglot Reality

A typical operational task might involve:

  1. Shell commands to check Kubernetes
  2. SQL query to verify database state
  3. Python script for data transformation
  4. cURL for API calls
  5. More shell to apply fixes

Each technology has its place. Your runbook needs to accommodate all of them.

Polyglot Runbook Structure

Using Multiple Languages in Markdown

Markdown’s fenced code blocks support language hints:

# Database Migration Runbook

## 1. Check current schema version
​```sql
SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1;
​```

## 2. Backup current data
​```bash
pg_dump -h db.internal production > backup-$(date +%Y%m%d).sql
​```

## 3. Run migration script
​```python
#!/usr/bin/env python3
from migration_runner import run_migrations
run_migrations(target_version='2024.01')
​```

## 4. Verify migration
​```sql
SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1;
​```

## 5. Smoke test API
​```bash
curl -s http://api.internal/health | jq '.database_version'
​```

Language-Specific Patterns

Bash: The Glue Language

Bash connects everything. Use it for:

  • Running CLI tools (kubectl, aws, gcloud)
  • Piping between commands
  • Quick checks and verifications
# Check and respond
if kubectl get pods -l app=api | grep -q CrashLoopBackOff; then
  echo "Pod crash detected"
  kubectl describe pods -l app=api | tail -20
else
  echo "Pods healthy"
fi

SQL: Direct Database Operations

For database checks and modifications:

-- Check connection count
SELECT count(*), state 
FROM pg_stat_activity 
GROUP BY state 
ORDER BY count DESC;

-- Check long-running queries
SELECT pid, now() - query_start as duration, query 
FROM pg_stat_activity 
WHERE state = 'active' 
  AND query_start < now() - interval '1 minute'
ORDER BY duration DESC;

Python: Complex Logic

When Bash gets unwieldy:

#!/usr/bin/env python3
"""Analyze logs for error patterns."""

import json
import subprocess
from collections import Counter

# Get logs
result = subprocess.run(
    ['kubectl', 'logs', '-l', 'app=api', '--tail=1000'],
    capture_output=True, text=True
)

# Parse and count errors
errors = Counter()
for line in result.stdout.split('\n'):
    if 'ERROR' in line:
        try:
            log = json.loads(line)
            errors[log.get('error_type', 'unknown')] += 1
        except json.JSONDecodeError:
            errors['parse_error'] += 1

# Report
for error_type, count in errors.most_common(10):
    print(f"{error_type}: {count}")

cURL/HTTP: API Operations

For REST API interactions:

# Health check with detailed timing
curl -w "\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -s http://api.internal/health | jq '.'

# POST with JSON body
curl -X POST http://api.internal/admin/cache/clear \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_TOKEN" \
  -d '{"scope": "all"}'

JQ: JSON Processing

For parsing JSON output:

# Extract specific fields
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'

# Filter and transform
curl -s http://api.internal/metrics | jq '.services[] | select(.healthy == false) | .name'

# Complex aggregation
kubectl get events -o json | jq '[.items[] | select(.type == "Warning")] | group_by(.reason) | map({reason: .[0].reason, count: length})'

Connecting Different Languages

Passing Data Between Steps

Sometimes you need output from one language as input to another.

Bash to SQL

# Get user ID from API
USER_ID=$(curl -s http://api.internal/users/search?email=user@example.com | jq -r '.id')

# Use in SQL query
psql -h db.internal -c "SELECT * FROM orders WHERE user_id = '$USER_ID';"

SQL to Bash

# Get value from database
COUNT=$(psql -h db.internal -t -c "SELECT count(*) FROM pending_jobs;")

# Use in conditional
if [ "$COUNT" -gt 100 ]; then
  echo "Job queue backing up: $COUNT pending"
  kubectl scale deployment/worker --replicas=5
fi

Python to Bash

# Run Python analysis, use result
THRESHOLD=$(python3 -c "
import statistics
data = [10, 20, 15, 25, 30]
print(int(statistics.mean(data) * 1.5))
")

echo "Using threshold: $THRESHOLD"

Runbook for a Real Mixed Stack

Here’s a complete polyglot runbook for a typical microservices environment:

# API Performance Investigation

## Overview
Use this runbook when API latency alerts fire.

## 1. Quick Status Check

### API Pods
​```bash
kubectl get pods -l app=api -o wide
kubectl top pods -l app=api
​```

### Error Rate
​```bash
curl -s http://prometheus:9090/api/v1/query?query=rate(http_errors_total[5m]) | jq '.data.result[0].value[1]'
​```

## 2. Database Investigation

### Connection Count
​```sql
SELECT count(*), state FROM pg_stat_activity GROUP BY state;
​```

### Slow Queries
​```sql
SELECT pid, now() - query_start as duration, substring(query, 1, 100)
FROM pg_stat_activity
WHERE state = 'active' AND query_start < now() - interval '5 seconds'
ORDER BY duration DESC
LIMIT 10;
​```

## 3. Log Analysis

### Recent Errors (Bash)
​```bash
kubectl logs -l app=api --tail=500 | grep -i error | tail -20
​```

### Error Distribution (Python)
​```python
#!/usr/bin/env python3
import subprocess
import json
from collections import Counter

result = subprocess.run(
    ['kubectl', 'logs', '-l', 'app=api', '--tail=1000'],
    capture_output=True, text=True
)

errors = Counter()
for line in result.stdout.split('\n'):
    if '"level":"error"' in line:
        try:
            log = json.loads(line)
            errors[log.get('msg', 'unknown')[:50]] += 1
        except:
            pass

for msg, count in errors.most_common(5):
    print(f"{count:4d} | {msg}")
​```

## 4. External Dependencies

### Check Third-Party APIs
​```bash
for endpoint in payment.api.com inventory.api.com shipping.api.com; do
  echo -n "$endpoint: "
  curl -s -o /dev/null -w "%{http_code} %{time_total}s" "https://$endpoint/health"
  echo
done
​```

## 5. Remediation Options

### If Database Slow
​```sql
-- Kill long-running query
SELECT pg_terminate_backend(PID);
​```

### If External Dependency Down
​```bash
# Enable circuit breaker
kubectl set env deployment/api CIRCUIT_BREAKER_ENABLED=true
​```

### If Resource Constrained
​```bash
kubectl scale deployment/api --replicas=5
​```

Tool Support for Polyglot Runbooks

Different tools handle multiple languages differently:

ToolBashPythonSQLHTTP
JupyterVia subprocessNativeVia libraryVia requests
Org-modeNativeNativeVia babelVia curl
RunmeNativeVia shebangVia psqlVia curl
StewNativeVia shebangVia clientsNative

Stew’s Polyglot Approach

Stew handles mixed technology stacks naturally:

  • Bash: Run directly
  • Python/Ruby/etc: Via shebang (#!/usr/bin/env python3)
  • SQL: Via database CLIs (psql, mysql)
  • HTTP: Built-in REST support

Your runbook reflects how you actually work—across languages and tools.

# Works in Stew as-is
​```bash
kubectl get pods
​```

​```python
#!/usr/bin/env python3
print("Analysis complete")
​```

​```bash
psql -c "SELECT count(*) FROM users;"
​```

Join the waitlist and write runbooks that match your stack.