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 = 2

Key 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 krawl

2. Attach PostgreSQL

fly postgres create --name krawl-db --region sjc
fly postgres attach krawl-db --app krawl

This 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 krawl

4. Deploy

fly deploy --app krawl

5. Verify

curl https://api.krawl.sh/health

Scaling

Vertical (more resources)

fly scale vm performance-2x --memory 8192 --app krawl

Horizontal

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 krawl

SSH

fly ssh console --app krawl

Metrics

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, metadata
  • sessions — research session tracking for continuity
  • lookouts — scheduled research configurations
  • audit_entries — audit trail entries
  • memories — 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_REGION defaults to us-east-1 — the us. 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 krawl

Database connection failures

Check the Fly Postgres cluster status:

fly postgres status --app krawl-db

Rate limiting

Default is 5 requests/minute per IP. Adjust via RATE_LIMIT env var:

fly secrets set RATE_LIMIT="10/minute" --app krawl

On this page