Skip to main content

Deployment

Work in Progress

This deployment documentation is currently being enhanced and refined. Some sections may be incomplete or subject to change. We're actively working on comprehensive examples and troubleshooting guides for all platforms.

flAPI is designed for deployment flexibility. Available as a single binary or Docker container, it runs on any platform that supports Linux containers or x86-64 binaries.

Quick Start

🚀 Interactive Deployment Configurator

Configure your deployment with config mounting strategy

Mount config from host filesystem
Generated Configuration
# 1. Create directory structure on host
mkdir -p ~/flapi/{config/sqls,data}

# 2. Create your flapi.yaml
cat > ~/flapi/config/flapi.yaml <<EOF
project_name: my-api
template:
  path: '/config/sqls'
connections:
  # Your connections here
duckdb:
  db_path: /data/flapi.db
EOF

# 3. Add your SQL templates
# cp your_templates.yaml ~/flapi/config/sqls/

# 4. Create docker-compose.yml
cat > ~/flapi/docker-compose.yml <<EOF
version: '3.8'
services:
  flapi:
    image: ghcr.io/datazoode/flapi:latest
    ports:
      - "8080:8080"
    volumes:
      - ./config:/config:ro
      - ./data:/data
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 2G
EOF

# 5. Deploy
cd ~/flapi && docker-compose up -d

Requirements

ResourceMinimumRecommendedNotes
CPU1 vCPU2 vCPUDuckDB is CPU-intensive for aggregations
Memory1 GB2-4 GBDepends on cache size
Storage1 GB10 GB+For DuckDB cache persistence
Port8080-Default HTTP port
Startup< 100ms-Fast cold starts for serverless

Configuration Management

Critical

flAPI requires configuration files to function. The base Docker image (ghcr.io/datazoode/flapi:latest) contains only the binary - you must mount your configuration to run it.

Standard Directory Structure

flAPI expects the following structure:

/config/
├── flapi.yaml # Main configuration file (required)
└── sqls/ # SQL template directory (required)
├── users.yaml # Endpoint definitions
├── products.yaml
└── orders.yaml

Minimal Example Configuration

Create flapi.yaml:

config/flapi.yaml
project_name: my-api
project_description: My flAPI deployment

template:
path: '/config/sqls' # Path to SQL templates

connections:
postgres:
connection_string: "postgresql://user:pass@host:5432/db"

duckdb:
db_path: /data/flapi.db # Cache database location
access_mode: READ_WRITE

Create your first endpoint sqls/users.yaml:

config/sqls/users.yaml
url-path: /users
sql: |
SELECT * FROM users
WHERE active = true
LIMIT 100

Configuration Mounting Strategies

Choose the approach that fits your deployment platform:

1️⃣ Local Volume Mount (Docker, VPS, K8s)

Best for: Development, VPS deployment, on-premises

Mount your local config directory directly into the container:

docker run -d \
-p 8080:8080 \
-v $(pwd)/config:/config:ro \
-v $(pwd)/data:/data \
ghcr.io/datazoode/flapi:latest

Advantages:

  • ✅ Simple and direct
  • ✅ Easy to update (edit files, restart container)
  • ✅ Works with any text editor

Disadvantages:

  • ❌ Requires host filesystem access
  • ❌ Not suitable for serverless platforms

2️⃣ Kubernetes ConfigMap (K8s, IONOS, STACKIT)

Best for: Kubernetes deployments, multi-replica setups

Create ConfigMaps from your config files:

# Create ConfigMap for main config
kubectl create configmap flapi-config \
--from-file=flapi.yaml=./config/flapi.yaml \
--namespace=flapi

# Create ConfigMap for SQL templates
kubectl create configmap flapi-sqls \
--from-file=./config/sqls/ \
--namespace=flapi

Mount in your Deployment:

volumeMounts:
- name: config
mountPath: /config/flapi.yaml
subPath: flapi.yaml
- name: sqls
mountPath: /config/sqls

volumes:
- name: config
configMap:
name: flapi-config
- name: sqls
configMap:
name: flapi-sqls

Advantages:

  • ✅ Native Kubernetes integration
  • ✅ Version controlled via kubectl
  • ✅ Can be updated without rebuilding images

Disadvantages:

  • ❌ ConfigMap size limit (1MB)
  • ❌ Requires kubectl access to update
tip

For large SQL template collections, use PersistentVolumes instead of ConfigMaps.

3️⃣ Cloud Storage Mount (Cloud Run, Lambda, Azure)

Best for: Serverless platforms, multi-region deployments

Google Cloud Run (GCS Bucket):

# 1. Upload config
gsutil -m cp -r ./config gs://my-bucket/flapi-config/

# 2. Deploy with GCS mount
gcloud run deploy flapi \
--image ghcr.io/datazoode/flapi:latest \
--add-volume=name=config,type=cloud-storage,bucket=my-bucket \
--add-volume-mount=volume=config,mount-path=/config

AWS Lambda (EFS Mount):

# 1. Create EFS file system
aws efs create-file-system --tags Key=Name,Value=flapi-config

# 2. Mount EFS to EC2, upload config to /config

# 3. Create Lambda with EFS mount
aws lambda create-function \
--function-name flapi \
--file-system-configs "Arn=arn:aws:elasticfilesystem:...,LocalMountPath=/config"

Advantages:

  • ✅ Works with serverless platforms
  • ✅ Centralized configuration storage
  • ✅ Can be shared across multiple instances

Disadvantages:

  • ❌ Increased cold start time
  • ❌ Additional cost for storage
  • ❌ More complex setup

4️⃣ Baked-In Configuration (Custom Image)

Best for: Immutable deployments, CI/CD pipelines

Create a custom Docker image with config baked in:

Dockerfile
FROM ghcr.io/datazoode/flapi:latest

# Copy configuration into image
COPY config/flapi.yaml /config/flapi.yaml
COPY config/sqls /config/sqls

# Optional: Set environment variables
ENV FLAPI_CONFIG=/config/flapi.yaml

CMD ["/app/flapi", "-c", "/config/flapi.yaml"]

Build and deploy:

docker build -t my-org/flapi:v1.0 .
docker push my-org/flapi:v1.0

Advantages:

  • ✅ Self-contained, portable image
  • ✅ Fastest cold start (no external mounts)
  • ✅ Works on any platform

Disadvantages:

  • ❌ Config changes require image rebuild
  • ❌ Larger image size
  • ❌ Less flexible
Security

Never bake secrets (database passwords, API keys) into images. Use environment variables or secret management instead.

Configuration Update Strategies

PlatformUpdate MethodDowntimeRollback
Docker ComposeEdit files → docker-compose restart< 1sManual (git revert)
Kuberneteskubectl apply configmap → Rolling update0skubectl rollout undo
Cloud RunUpdate GCS bucket → Redeploy~30sDeploy previous revision
Custom ImageRebuild → Push → Deploy~2-5minDeploy previous tag

Configuration Validation

Before deploying, validate your configuration:

# Run flAPI locally to check for errors
docker run --rm \
-v $(pwd)/config:/config \
ghcr.io/datazoode/flapi:latest \
--dry-run

# Check YAML syntax
yamllint config/flapi.yaml config/sqls/*.yaml

# Test SQL templates
# (flAPI will validate SQL on startup)

Environment Variables

Override config values using environment variables:

# Docker
docker run -e FLAPI_DB_PATH=/data/custom.db ...

# Kubernetes
env:
- name: FLAPI_DB_PATH
value: /data/custom.db
- name: PG_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password

Common environment variables:

VariablePurposeExample
FLAPI_CONFIGOverride config file path/config/flapi.yaml
FLAPI_PORTOverride HTTP port8080
FLAPI_LOG_LEVELSet log verbositydebug, info, warn

Enterprise Cloud Platforms

Google Cloud Run

Best for: Serverless container deployment with auto-scaling to zero

# Deploy to Cloud Run
gcloud run deploy flapi \
--image ghcr.io/datazoode/flapi:latest \
--platform managed \
--region europe-west1 \
--port 8080 \
--memory 2Gi \
--cpu 1 \
--allow-unauthenticated \
--set-env-vars="FLAPI_CONFIG=/config/flapi.yaml"

Pricing: Pay per request, scales to zero

  • Free tier: 2 million requests/month
  • Cost: ~$0.00002400 per request (beyond free tier)

AWS App Runner

Best for: Fully managed container service with simple deployment

# Create apprunner.yaml
version: 1.0
runtime: python3
build:
commands:
image: ghcr.io/datazoode/flapi:latest
run:
runtime-version: 3.8
command: /app/flapi -c /config/flapi.yaml
network:
port: 8080
env:
- name: FLAPI_ENV
value: production

# Deploy
aws apprunner create-service \
--service-name flapi \
--source-configuration file://apprunner.yaml

Pricing: Pay for active time

  • Cost: ~$0.064/vCPU-hour + $0.007/GB-hour

AWS Lambda

Best for: Sporadic traffic patterns, event-driven workloads

# Package as container image
docker build -t flapi-lambda .

# Push to ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin ACCOUNT.dkr.ecr.us-east-1.amazonaws.com
docker push ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/flapi:latest

# Create function
aws lambda create-function \
--function-name flapi \
--package-type Image \
--code ImageUri=ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/flapi:latest \
--role arn:aws:iam::ACCOUNT:role/lambda-flapi \
--memory-size 2048 \
--timeout 30 \
--environment "Variables={FLAPI_CONFIG=/config/flapi.yaml}"
Cache Persistence

Lambda containers are ephemeral. Use EFS for persistent DuckDB cache:

--file-system-config Arn=arn:aws:elasticfilesystem:REGION:ACCOUNT:access-point/ACCESS_POINT

Pricing: Pay per invocation

  • Free tier: 1M requests + 400,000 GB-seconds/month
  • Cost: $0.20 per 1M requests + $0.0000166667 per GB-second

Azure Container Apps

Best for: Kubernetes-based microservices without cluster management

az containerapp create \
--name flapi \
--resource-group myResourceGroup \
--image ghcr.io/datazoode/flapi:latest \
--target-port 8080 \
--ingress external \
--min-replicas 1 \
--max-replicas 10 \
--cpu 1.0 \
--memory 2.0Gi \
--env-vars FLAPI_CONFIG=/config/flapi.yaml

Pricing: Pay for vCPU and memory

  • Cost: ~$0.000012/vCPU-second + $0.000002/GB-second

European Cloud Providers

IONOS Cloud

Best for: German/European data sovereignty, GDPR compliance

IONOS provides managed Kubernetes and container hosting with data centers in Germany and Spain.

# Install IONOS CLI
curl -sL https://github.com/ionos-cloud/ionosctl/releases/latest/download/ionosctl-linux-amd64.tar.gz | tar -xzv

# Create Kubernetes cluster (if not exists)
ionosctl k8s cluster create \
--name flapi-cluster \
--k8s-version 1.28 \
--datacenter-id DATACENTER_ID

# Deploy flAPI
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: flapi
labels:
app: flapi
spec:
replicas: 2
selector:
matchLabels:
app: flapi
template:
metadata:
labels:
app: flapi
spec:
containers:
- name: flapi
image: ghcr.io/datazoode/flapi:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
cpu: "2"
volumeMounts:
- name: config
mountPath: /config
- name: data
mountPath: /data
volumes:
- name: config
persistentVolumeClaim:
claimName: flapi-config
- name: data
persistentVolumeClaim:
claimName: flapi-data
---
apiVersion: v1
kind: Service
metadata:
name: flapi
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: flapi
EOF

Key Features:

  • Data centers: Frankfurt (de/fra), Berlin (de/txl), Logroño (es/vit)
  • GDPR-compliant infrastructure
  • ISO 27001 certified
  • German support

Pricing: Managed Kubernetes

  • Cost: ~€0.10/hour per worker node + €0.01/GB storage

STACKIT

Best for: Schwarz Group ecosystem, German cloud sovereignty

# Create STACKIT Kubernetes cluster via portal or CLI
stackit kubernetes cluster create \
--project-id PROJECT_ID \
--name flapi-cluster

# Get kubeconfig
stackit kubernetes credentials get \
--cluster-id CLUSTER_ID \
--project-id PROJECT_ID

# Deploy flAPI
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: flapi
spec:
replicas: 2
selector:
matchLabels:
app: flapi
template:
metadata:
labels:
app: flapi
spec:
containers:
- name: flapi
image: ghcr.io/datazoode/flapi:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "2Gi"
cpu: "1000m"
---
apiVersion: v1
kind: Service
metadata:
name: flapi
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: flapi
EOF

Key Features:

  • German data centers (operated by Schwarz Digits)
  • Enterprise SLA
  • Direct integration with SAP systems
  • Carbon-neutral operations

Kubernetes

Generic Kubernetes Deployment

Best for: Multi-cloud portability, full control, enterprise scale

Create a complete flAPI deployment with persistent storage and horizontal scaling:

flapi-k8s.yaml
# Namespace
apiVersion: v1
kind: Namespace
metadata:
name: flapi

---
# ConfigMap for flapi.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: flapi-config
namespace: flapi
data:
flapi.yaml: |
project_name: production-api
project_description: Production flAPI deployment
template:
path: '/config/sqls'
connections:
# Your connections here
duckdb:
db_path: /data/flapi.db
access_mode: READ_WRITE

---
# PersistentVolumeClaim for DuckDB cache
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: flapi-data
namespace: flapi
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: standard

---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: flapi
namespace: flapi
labels:
app: flapi
spec:
replicas: 3
selector:
matchLabels:
app: flapi
template:
metadata:
labels:
app: flapi
spec:
containers:
- name: flapi
image: ghcr.io/datazoode/flapi:latest
ports:
- containerPort: 8080
name: http
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
cpu: "2"
volumeMounts:
- name: config
mountPath: /config
- name: data
mountPath: /data
env:
- name: FLAPI_ENV
value: "production"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: config
configMap:
name: flapi-config
- name: data
persistentVolumeClaim:
claimName: flapi-data

---
# Service
apiVersion: v1
kind: Service
metadata:
name: flapi
namespace: flapi
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: flapi

---
# HorizontalPodAutoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: flapi
namespace: flapi
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: flapi
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

Deploy:

kubectl apply -f flapi-k8s.yaml

Ingress Configuration

For production deployments, add an Ingress with TLS:

flapi-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flapi
namespace: flapi
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.yourdomain.com
secretName: flapi-tls
rules:
- host: api.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: flapi
port:
number: 80

Indie Hacker Platforms

Fly.io

Best for: Edge deployment, global distribution, developer experience

# Install flyctl
curl -L https://fly.io/install.sh | sh

# Launch flAPI
fly launch \
--image ghcr.io/datazoode/flapi:latest \
--name flapi-app \
--region fra \
--vm-size shared-cpu-2x \
--vm-memory 2048

# Add persistent volume for cache
fly volumes create flapi_data --region fra --size 10

# Update fly.toml for volume
cat > fly.toml <<EOF
app = "flapi-app"

[build]
image = "ghcr.io/datazoode/flapi:latest"

[[mounts]]
source = "flapi_data"
destination = "/data"

[[services]]
internal_port = 8080
protocol = "tcp"

[[services.ports]]
handlers = ["http"]
port = 80

[[services.ports]]
handlers = ["tls", "http"]
port = 443
EOF

# Deploy
fly deploy

Pricing: Free tier available

  • Free: 3 shared-cpu-1x VMs (256MB RAM)
  • Paid: ~$0.0000022/second for shared-cpu-2x (2GB RAM)

Railway

Best for: Git-based deployment, simple setup, PostgreSQL integration

# Install Railway CLI
npm i -g @railway/cli

# Login
railway login

# Initialize project
railway init

# Deploy from Docker image
railway up --image ghcr.io/datazoode/flapi:latest

# Or use railway.json for configuration
cat > railway.json <<EOF
{
"build": {
"dockerImage": "ghcr.io/datazoode/flapi:latest"
},
"deploy": {
"startCommand": "/app/flapi -c /config/flapi.yaml",
"restartPolicyType": "ON_FAILURE",
"healthcheckPath": "/health",
"healthcheckTimeout": 100
}
}
EOF

Pricing: $5 credit/month on free plan

  • Free: $5/month credit (covers ~500 hours)
  • Paid: $0.000231/GB-hour RAM + $0.00463/vCPU-hour

Render

Best for: Free tier for testing, managed services

# Create render.yaml
cat > render.yaml <<EOF
services:
- type: web
name: flapi
env: docker
image:
url: ghcr.io/datazoode/flapi:latest
plan: starter
healthCheckPath: /health
envVars:
- key: FLAPI_ENV
value: production
disk:
name: flapi-data
mountPath: /data
sizeGB: 10
EOF

# Deploy via Render Dashboard or CLI
render deploy

Pricing: Free tier available

  • Free: 750 hours/month, sleeps after inactivity
  • Starter: $7/month (persistent, no sleep)
  • Standard: $25/month (2 GB RAM, 1 vCPU)

DigitalOcean App Platform

Best for: Predictable pricing, managed databases, simple scaling

# Create .do/app.yaml
mkdir -p .do
cat > .do/app.yaml <<EOF
name: flapi
services:
- name: api
image:
registry_type: GHCR
repository: datazoode/flapi
tag: latest
http_port: 8080
instance_count: 2
instance_size_slug: basic-xs
routes:
- path: /
health_check:
http_path: /health
envs:
- key: FLAPI_ENV
value: production
EOF

# Deploy via doctl
doctl apps create --spec .do/app.yaml

# Or use DigitalOcean Dashboard

Pricing: Predictable monthly cost

  • Basic (512MB): $5/month
  • Basic (1GB): $12/month
  • Professional (2GB): $24/month

Cost-Effective VPS

Hetzner Cloud

Best for: European hosting, best price/performance ratio

# Create server via CLI
hcloud server create \
--name flapi \
--type cx21 \
--image docker-ce \
--ssh-key my-key

# SSH into server
ssh root@YOUR_SERVER_IP

# Create docker-compose.yml
cat > docker-compose.yml <<EOF
version: '3.8'
services:
flapi:
image: ghcr.io/datazoode/flapi:latest
container_name: flapi
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config:/config:ro
- ./data:/data
- ./sqls:/sqls:ro
environment:
- FLAPI_ENV=production
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

# Optional: Caddy for HTTPS
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config

volumes:
caddy_data:
caddy_config:
EOF

# Create Caddyfile for HTTPS
cat > Caddyfile <<EOF
api.yourdomain.com {
reverse_proxy flapi:8080

# Enable compression
encode gzip

# Security headers
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
}
EOF

# Start services
docker-compose up -d

# View logs
docker-compose logs -f flapi

Pricing: Excellent value

  • CX11 (2GB): €4.15/month (~$4.50)
  • CX21 (4GB): €5.83/month (~$6.35)
  • CX31 (8GB): €10.59/month (~$11.50)

Self-Hosted

Systemd Service (Linux Binary)

For running flAPI as a native Linux service without Docker:

# Download flAPI binary
curl -L https://github.com/datazoode/flapi/releases/latest/download/flapi \
-o /usr/local/bin/flapi
chmod +x /usr/local/bin/flapi

# Create flapi user
sudo useradd -r -s /bin/false flapi

# Create directories
sudo mkdir -p /etc/flapi/{sqls,config}
sudo mkdir -p /var/lib/flapi/data
sudo chown -R flapi:flapi /etc/flapi /var/lib/flapi

# Create systemd service
sudo tee /etc/systemd/system/flapi.service > /dev/null <<EOF
[Unit]
Description=flAPI REST API Service
Documentation=https://flapi.io
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=flapi
Group=flapi
ExecStart=/usr/local/bin/flapi -c /etc/flapi/flapi.yaml
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=5
WorkingDirectory=/var/lib/flapi

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/flapi

# Resource limits
LimitNOFILE=65536
MemoryLimit=4G

[Install]
WantedBy=multi-user.target
EOF

# Copy your configuration
sudo cp flapi.yaml /etc/flapi/
sudo cp -r sqls/* /etc/flapi/sqls/
sudo chown -R flapi:flapi /etc/flapi

# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable flapi
sudo systemctl start flapi

# Check status
sudo systemctl status flapi

# View logs
sudo journalctl -u flapi -f

Production Checklist

Before deploying to production, ensure you have:

Security

  • Enable HTTPS/TLS (Let's Encrypt, Cloudflare, load balancer)
  • Configure authentication (JWT, API keys)
  • Set up rate limiting
  • Whitelist environment variables in config
  • Review row-level security in SQL templates
  • Use secrets management (not hardcoded)

Monitoring

  • Configure health check endpoint (/health)
  • Set up metrics collection (Prometheus, CloudWatch)
  • Configure logging (structured JSON logs)
  • Set up alerting (uptime, error rates, cache hits)
  • Monitor cache refresh success/failures

Performance

  • Size memory for your cache needs
  • Configure cache refresh schedules
  • Set up horizontal scaling (HPA)
  • Test under expected load
  • Configure connection pooling

Backup & Recovery

  • Back up DuckDB cache database
  • Back up configuration files
  • Document recovery procedures
  • Test restore process
  • Set up automated backups

High Availability

  • Run multiple replicas (3+ for production)
  • Use load balancer with health checks
  • Configure pod/service disruption budgets
  • Set up multi-region if needed
  • Test failover scenarios

Troubleshooting

Port Already in Use

# Find process using port 8080
lsof -i :8080
sudo netstat -tulpn | grep 8080

# Kill process or use different port
flapi -c config.yaml --port 8081

Permission Denied (Docker)

# Run with correct user permissions
docker run --user $(id -u):$(id -g) \
-v $(pwd)/config:/config \
ghcr.io/datazoode/flapi:latest

Cache Not Persisting

# Ensure volume mount for DuckDB
-v $(pwd)/data:/data

# Check DuckDB path in config
duckdb:
db_path: /data/flapi.db # Must be on mounted volume

Memory Issues

# Increase container memory limits
docker run -m 4g ghcr.io/datazoode/flapi:latest

# Or in Kubernetes
resources:
limits:
memory: "4Gi"

Configuration Not Found

Error: flapi.yaml not found or Config file missing

# Check if config is mounted
docker exec CONTAINER_ID ls -la /config

# Should show:
# /config/flapi.yaml
# /config/sqls/

# Fix: Ensure volume mount is correct
docker run -v $(pwd)/config:/config:ro ...

# Or check ConfigMap in Kubernetes
kubectl describe configmap flapi-config -n flapi

SQL Templates Not Loading

Error: No endpoints found or Template directory empty

# Verify template path in flapi.yaml
template:
path: '/config/sqls' # Must match mounted path

# Check files exist
docker exec CONTAINER_ID ls -la /config/sqls

# Ensure YAML files have correct structure
cat config/sqls/users.yaml
# Must contain:
# url-path: /users
# sql: |
# SELECT ...

Invalid YAML Syntax

Error: YAML parse error or Invalid configuration

# Validate YAML syntax locally
yamllint config/flapi.yaml

# Common issues:
# - Incorrect indentation (use spaces, not tabs)
# - Missing quotes around special characters
# - Trailing whitespace

# Test configuration before deploying
docker run --rm \
-v $(pwd)/config:/config \
ghcr.io/datazoode/flapi:latest \
--dry-run

Connection Refused / Database Unreachable

Error: Connection refused or Host unreachable

# Inside container, host.docker.internal points to host machine
connections:
postgres:
connection_string: "postgresql://user:pass@host.docker.internal:5432/db"

# In Kubernetes, use service DNS
connections:
postgres:
connection_string: "postgresql://user:pass@postgres.default.svc.cluster.local:5432/db"

# Test connection from within container
docker exec CONTAINER_ID ping postgres-host

ConfigMap Size Limit Exceeded

Error: ConfigMap too large (> 1MB)

# Solution 1: Split into multiple ConfigMaps
kubectl create configmap flapi-sqls-users --from-file=./config/sqls/users/
kubectl create configmap flapi-sqls-products --from-file=./config/sqls/products/

# Solution 2: Use PersistentVolume instead
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: flapi-config
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi

# Upload config to PV manually or via init container

Read-Only Filesystem Errors

Error: Read-only file system when writing cache

# Ensure data directory is writable
docker run -v $(pwd)/data:/data ... # No :ro flag

# In Kubernetes, use ReadWriteOnce PVC for /data
volumes:
- name: data
persistentVolumeClaim:
claimName: flapi-data # Must be RWO, not RO

Environment Variable Not Working

Error: Config value not overridden by env var

# Check environment variables are set
docker exec CONTAINER_ID env | grep FLAPI

# Verify variable names match flAPI conventions
# Use UPPERCASE with underscores
FLAPI_DB_PATH=/data/custom.db # ✅ Correct
flapi-db-path=/data/custom.db # ❌ Wrong

# In Kubernetes, check pod env
kubectl describe pod flapi-xxx -n flapi | grep -A5 Environment

Cloud Storage Mount Failing

Google Cloud Run:

# Ensure service account has Storage Object Viewer role
gcloud projects add-iam-policy-binding PROJECT_ID \
--member=serviceAccount:SERVICE_ACCOUNT \
--role=roles/storage.objectViewer

# Check bucket permissions
gsutil iam get gs://YOUR_BUCKET

# Verify files are in bucket
gsutil ls gs://YOUR_BUCKET/flapi-config/

AWS Lambda (EFS):

# Check EFS mount target is in same VPC as Lambda
aws efs describe-mount-targets --file-system-id fs-xxx

# Verify Lambda has VPC permissions
# Security groups must allow NFS (port 2049)

# Check EFS access point
aws efs describe-access-points --file-system-id fs-xxx

Startup Crashes / Immediate Exit

Error: Container starts then exits immediately

# Check logs for actual error
docker logs CONTAINER_ID
kubectl logs pod/flapi-xxx -n flapi

# Common causes:
# 1. Missing config file
# 2. Invalid YAML syntax
# 3. Database connection failure
# 4. Port already in use

# Run interactively to debug
docker run -it --rm \
-v $(pwd)/config:/config \
ghcr.io/datazoode/flapi:latest \
sh

# Then manually test:
/app/flapi -c /config/flapi.yaml

Next Steps

Need help with deployment? Check out our professional services or join the community.

🍪 Cookie Settings