justapi — /docs

JustAPI Troubleshooting Guide

Common issues and solutions for JustAPI deployments.


Table of Contents

  1. GIL Deadlock
  2. Connection Pool Exhaustion
  3. TLS Certificate Issues
  4. WebSocket Connection Failures
  5. High Memory Usage
  6. Slow Response Times
  7. Database Connection Errors
  8. Rate Limiting Issues
  9. GraphQL Errors
  10. Deployment Issues

1. GIL Deadlock

Symptoms

  • Server stops responding to requests
  • CPU usage drops to near zero
  • Logs show no new request processing

Cause

JustAPI uses a dedicated GIL pool to avoid blocking Tokio worker threads. If the GIL pool workers are all busy or the GIL is held too long, requests queue up.

Solution

Check GIL pool status:

import justapi
app = JustAPIApp()
# GIL pool is initialized automatically on first request

Increase GIL pool size (if needed): The pool size is auto-detected based on CPU cores. For CPython (GIL enabled), it defaults to 1 worker. For free-threaded Python, it scales with cores.

Verify no blocking calls in handlers:

# BAD: Blocks the GIL pool
import time
time.sleep(5)

# GOOD: Use async sleep
import asyncio
await asyncio.sleep(5)

Check for long-running synchronous operations:

# BAD: Synchronous database call blocks GIL pool
result = db.execute("SELECT * FROM users")

# GOOD: Use async database operations
result = await db.execute_async("SELECT * FROM users")

2. Connection Pool Exhaustion

Symptoms

  • 503 Service Unavailable responses
  • connection pool exhausted errors in logs
  • Increasing latency under load

Cause

Too many concurrent database connections or connections not being released.

Solution

Check pool configuration:

from justapi import JustAPIApp, Database

app = JustAPIApp()
db = Database("postgres://user:pass@localhost/db")
app.set_database(db, max_connections=20)  # Default is 10

Monitor active connections:

# PostgreSQL
SELECT count(*) FROM pg_stat_activity;

# Check for idle connections
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;

Enable connection pool monitoring:

# Check pool health
pool_health = await app.db_pool.health_check()
print(f"Pool status: {pool_health}")

Increase pool size (if needed):

db = Database("postgres://user:pass@localhost/db", max_connections=50)

Reduce connection hold time:

# BAD: Long transaction holds connection
async with db.transaction():
    result = await db.execute("SELECT * FROM large_table")
    # ... process for 10 seconds ...
    await db.execute("UPDATE ...")

# GOOD: Short transactions
result = await db.execute("SELECT * FROM large_table")
# ... process ...
async with db.transaction():
    await db.execute("UPDATE ...")

3. TLS Certificate Issues

Symptoms

  • certificate verify failed errors
  • Browser shows certificate warnings
  • WebSocket connections fail over TLS

Cause

Invalid, expired, or misconfigured TLS certificates.

Solution

Verify certificate validity:

openssl x509 -in cert.pem -noout -dates
openssl x509 -in cert.pem -noout -subject

Check certificate chain:

openssl verify -CAfile ca.pem cert.pem

Generate self-signed certificate (development only):

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

Verify TLS configuration in JustAPI:

from justapi import JustAPIApp

app = JustAPIApp()
app.run(
    addr="0.0.0.0:8443",
    tls_cert="cert.pem",
    tls_key="key.pem"
)

Check for common TLS issues: 1. Certificate expired → renew 2. Wrong private key → ensure key matches certificate 3. Missing intermediate certificates → bundle CA chain 4. hostname mismatch → certificate must cover the domain


4. WebSocket Connection Failures

Symptoms

  • WebSocket connections immediately close
  • WebSocket connection failed errors
  • Connections establish but no data flows

Cause

Firewall blocking upgrades, proxy misconfiguration, or handler errors.

Solution

Verify WebSocket endpoint is registered:

from justapi import JustAPIApp

app = JustAPIApp()

@app.websocket("/ws")
async def websocket_handler(ws):
    await ws.accept()
    data = await ws.receive_text()
    await ws.send_text(f"Echo: {data}")

Check proxy configuration (if behind nginx/HAProxy):

# nginx configuration
location /ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;
}

Test WebSocket connectivity:

# Using websocat
websocat ws://localhost:8000/ws

# Using wscat
npx wscat -c ws://localhost:8000/ws

Check for firewall issues:

# Test if port is open
telnet localhost 8000

# Check if WebSocket upgrade works
curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  http://localhost:8000/ws

5. High Memory Usage

Symptoms

  • Process RSS grows continuously
  • Out of memory kills
  • Swap usage increases

Cause

Memory leaks, large response buffering, or connection leaks.

Solution

Monitor memory usage:

# Process memory
ps aux | grep justapi

# Detailed memory map
pmap -x <pid>

# Continuous monitoring
watch -n 1 'ps -o pid,rss,vsz -p <pid>'

Check for connection leaks:

# Ensure connections are properly closed
async with db.connection() as conn:
    result = await conn.execute("SELECT ...")
# Connection automatically returned to pool

Reduce response buffering:

# BAD: Large response fully buffered
@app.get("/large")
async def large_response():
    return {"data": "x" * 10_000_000}  # 10MB

# GOOD: Stream large responses
@app.get("/stream")
async def stream_response():
    async def generate():
        for i in range(1000):
            yield f"chunk {i}\n"
    return StreamingResponse(generate())

Enable memory profiling:

# Using mprof (memory_profiler)
mprof run python app.py

# Analyze results
mprof plot

6. Slow Response Times

Symptoms

  • High p99 latency
  • Timeouts under load
  • Slow TTFB (Time to First Byte)

Cause

Slow database queries, blocking operations, or middleware overhead.

Solution

Profile request handling:

import time

@app.middleware("http")
async def timing_middleware(request, call_next):
    start = time.time()
    response = await call_next(request)
    duration = time.time() - start
    print(f"Request took {duration:.3f}s")
    return response

Check database query performance:

-- PostgreSQL: Enable slow query logging
ALTER SYSTEM SET log_min_duration_statement = 1000;  -- 1 second
SELECT pg_reload_conf();

-- Check for slow queries
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;

Verify middleware overhead:

# Disable middleware temporarily for testing
app = JustAPIApp(middlewares=[])  # No middleware

Check network latency:

# Measure round-trip time
ping localhost

# Check DNS resolution time
dig localhost

7. Database Connection Errors

Symptoms

  • connection refused errors
  • too many connections errors
  • connection timeout errors

Cause

Database server overload, incorrect connection string, or pool misconfiguration.

Solution

Verify connection string:

from justapi import JustAPIApp, Database

# Correct format
db = Database("postgres://user:password@host:5432/dbname")

# Common mistakes
# Wrong: postgres://user:pass@host/db (missing port)
# Wrong: postgresql://user:pass@host:5432/db (wrong scheme)

Test database connectivity:

# PostgreSQL
psql -h localhost -U user -d dbname

# MySQL
mysql -h localhost -u user -p dbname

# SQLite
sqlite3 database.db

Check database server status:

# PostgreSQL
sudo systemctl status postgresql

# MySQL
sudo systemctl status mysql

Increase connection timeout:

db = Database(
    "postgres://user:pass@localhost/db",
    connect_timeout=30,  # seconds
    pool_timeout=30
)

8. Rate Limiting Issues

Symptoms

  • 429 Too Many Requests responses
  • Legitimate requests being blocked
  • Inconsistent rate limiting behavior

Cause

Rate limit configuration too aggressive or Redis connection issues.

Solution

Check rate limit configuration:

from justapi import JustAPIApp

app = JustAPIApp()
# Default: 100 requests per minute
app.set_rate_limit(max_requests=1000, window_seconds=60)

Verify Redis connection (if using distributed rate limiting):

redis-cli ping
redis-cli info clients

Check rate limit headers:

curl -I http://localhost:8000/api/endpoint
# Look for:
# X-RateLimit-Limit: 100
# X-RateLimit-Remaining: 95
# Retry-After: 30

Adjust rate limits per endpoint:

@app.get("/api/public", rate_limit={"max_requests": 1000, "window_seconds": 60})
async def public_endpoint():
    return {"message": "public"}

@app.get("/api/sensitive", rate_limit={"max_requests": 10, "window_seconds": 60})
async def sensitive_endpoint():
    return {"message": "sensitive"}

9. GraphQL Errors

Symptoms

  • Query depth exceeded errors
  • Query complexity exceeded errors
  • GraphiQL not accessible

Cause

Query too complex or GraphiQL disabled in production.

Solution

Check query depth/complexity:

from justapi import JustAPIApp

app = JustAPIApp()
# Default limits: depth=10, complexity=200
app.graphql(depth_limit=20, complexity_limit=500)

Enable GraphiQL (development only):

# Set environment variable
export JUSTAPI_ENABLE_GRAPHIQL=1
python app.py

Simplify complex queries:

# BAD: Deeply nested query
query {
  users {
    posts {
      comments {
        author {
          name
        }
      }
    }
  }
}

# GOOD: Use fragments and aliases
query {
  users {
    id
    name
    postCount
  }
}

10. Deployment Issues

Symptoms

  • Container fails to start
  • Health checks fail
  • Pod restarts frequently

Cause

Misconfigured environment variables, resource limits, or health checks.

Solution

Verify environment variables:

# Check required variables
echo $DATABASE_URL
echo $REDIS_URL
echo $JUSTAPI_SECRET_KEY

Check container logs:

docker logs <container_id>
kubectl logs <pod_name>

Verify health check endpoint:

curl http://localhost:8000/health
# Should return: {"status": "healthy"}

Check resource limits:

# Kubernetes resource limits
resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"

Verify file permissions:

# Check secret files
ls -la /run/secrets/
# Should be: -rw------- 1 root root

# Fix permissions if needed
chmod 600 /run/secrets/*

Getting Help

If you can't resolve your issue:

  1. Check the logs for error messages
  2. Search GitHub Issues for similar problems
  3. Run diagnostics: bash justapi doctor
  4. Enable debug logging: bash export RUST_LOG=debug python app.py
  5. Open a GitHub Issue with:
  6. JustAPI version
  7. Python version
  8. Error message
  9. Steps to reproduce

JustAPI v2.0.9 — Open Source MIT License · Built with WebTUI · GitHub

NORMAL master justapi/docs
utf-8 Top 1:1