Deployment
Production deployment on Fly.io — Docker, PostgreSQL, scaling, and configuration
Krawl deploys on Fly.io as a single-machine Docker deployment with attached PostgreSQL.
Dockerfile
FROM python:3.12-slim
# Install uv for fast dependency management
COPY --from=ghcr.io/astral-sh/uv:0.7.12 /uv /usr/local/bin/uv
WORKDIR /app
# Copy dependency file first for layer caching
COPY pyproject.toml .
# Install dependencies into the system python (no venv needed in container)
RUN uv pip install --system --no-cache -r pyproject.toml
# Copy application code
COPY app/ app/
# Expose port
EXPOSE 8080
# Non-root user
RUN useradd -r -s /bin/false appuser
USER appuser
# Run with uvicorn
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080", "--workers", "1", "--timeout-graceful-shutdown", "30"]Key points:
- Python 3.12 slim base image
- uv for fast dependency installation (~5x faster than pip)
- Non-root user for security
- Single worker — Krawl uses asyncio concurrency, not multiprocessing
- 30s graceful shutdown — allows in-flight research to complete
fly.toml
app = "krawl"
primary_region = "sjc"
[build]
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = "suspend"
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[[vm]]
memory = "4gb"
cpu_kind = "performance"
cpus = 2Key settings:
- 4GB RAM — needed for concurrent research sessions and LLM response processing
- Performance CPU (2 cores) — for async I/O and parallel search execution
- auto_stop = suspend — machine suspends when idle, starts on request
- min_machines = 1 — always at least one machine ready
- force_https — all traffic over TLS
Setup from Scratch
1. Create the App
fly apps create krawl2. Attach PostgreSQL
fly postgres create --name krawl-db --region sjc
fly postgres attach krawl-db --app krawlThis sets DATABASE_URL automatically.
3. Set Secrets
# Required
fly secrets set EXA_API_KEY="..." --app krawl
fly secrets set GITHUB_TOKEN="..." --app krawl
fly secrets set COINGECKO_API_KEY="..." --app krawl
# LLM providers (set at least one pair)
fly secrets set AWS_BEDROCK_ACCESS_KEY_ID="..." --app krawl
fly secrets set AWS_BEDROCK_SECRET_ACCESS_KEY="..." --app krawl
fly secrets set ANTHROPIC_API_KEY="..." --app krawl
# Auth
fly secrets set MOGRA_API_KEY="your-secret-api-key" --app krawl
# Optional
fly secrets set XAI_API_KEY="..." --app krawl
fly secrets set FIRECRAWL_API_KEY="..." --app krawl
fly secrets set NANSEN_API_KEY="..." --app krawl
fly secrets set LUNARCRUSH_API_KEY="..." --app krawl
fly secrets set COINGLASS_API_KEY="..." --app krawl
fly secrets set MESSARI_API_KEY="..." --app krawl4. Deploy
fly deploy --app krawl5. Verify
curl https://api.krawl.sh/healthScaling
Vertical (more resources)
fly scale vm performance-2x --memory 8192 --app krawlHorizontal
Krawl uses in-memory state (active research sessions, circuit breaker). Horizontal scaling requires sticky sessions or external state management. For most use cases, a single machine with 4–8GB RAM handles the load.
Monitoring
Logs
fly logs --app krawlSSH
fly ssh console --app krawlMetrics
Fly.io provides built-in metrics for CPU, memory, and network. The /health endpoint returns version info for uptime monitoring.
Database Schema
Krawl auto-creates its PostgreSQL schema on startup (in the lifespan handler). Tables include:
results— persisted research results with markdown, sources, metadatasessions— research session tracking for continuitylookouts— scheduled research configurationsaudit_entries— audit trail entriesmemories— cross-session knowledge base
Environment Variables
All config is via environment variables. See Getting Started for the full list.
Key production considerations:
- Always set
MOGRA_API_KEY— without it, the API is publicly accessible - Set both Bedrock and Anthropic keys — for automatic fallback
AWS_BEDROCK_REGIONdefaults tous-east-1— theus.cross-region profiles handle routing
Troubleshooting
Machine keeps suspending during research
Increase the idle timeout or set auto_stop_machines = "off" in fly.toml.
Out of memory
Research sessions with high breadth/depth can use significant memory. Scale to 8GB:
fly scale vm performance-2x --memory 8192 --app krawlDatabase connection failures
Check the Fly Postgres cluster status:
fly postgres status --app krawl-dbRate limiting
Default is 5 requests/minute per IP. Adjust via RATE_LIMIT env var:
fly secrets set RATE_LIMIT="10/minute" --app krawl