Local Development Deployment¶
This guide walks you through setting up Felix for local development, running the broker on your machine, and configuring it for different development scenarios.
Prerequisites¶
Before running Felix locally, ensure you have:
- Rust 1.92.0 or later: Install via rustup
- Git: For cloning the repository
- Optional: Task for convenience commands
- At least 4GB RAM: Recommended for comfortable development
- Ports available: Default ports 5000 (QUIC) and 8080 (metrics)
Quick Start¶
Clone and Build¶
# Clone the repository
git clone https://github.com/gabloe/felix.git
cd felix
# Build the workspace in release mode
cargo build --workspace --release
Release vs Debug Builds
Always use release builds (--release) for performance testing. Debug builds have significantly higher overhead and can show 10-100x worse latency characteristics. Use debug builds only for debugging with tools like gdb or lldb.
Start the Broker¶
Run the broker with default settings:
Expected output:
2026-01-25T10:00:00.000Z INFO felix_broker: Starting Felix broker
2026-01-25T10:00:00.001Z INFO felix_broker: QUIC listening on 0.0.0.0:5000
2026-01-25T10:00:00.001Z INFO felix_broker: Metrics server on 0.0.0.0:8080
The broker is now accepting connections on:
- QUIC data plane:
0.0.0.0:5000(UDP) - Metrics/health HTTP:
0.0.0.0:8080(TCP)
Verify the Broker¶
Check that the broker is running:
# Check QUIC listener (requires lsof or ss)
lsof -i UDP:5000
# Check metrics endpoint
curl http://localhost:8080/healthz
Configuration Methods¶
Felix supports three configuration methods, applied in this order (later sources override earlier ones):
- Built-in defaults: Sensible defaults for local development
- Environment variables: Quick overrides via
FELIX_*variables - YAML config file: Structured configuration for complex setups
Using Environment Variables¶
The simplest way to configure Felix locally:
# Change broker ports
export FELIX_QUIC_BIND="0.0.0.0:5001"
export FELIX_BROKER_METRICS_BIND="0.0.0.0:8081"
# Enable publish acknowledgements
export FELIX_ACK_ON_COMMIT="true"
# Tune batching for lower latency
export FELIX_EVENT_BATCH_MAX_DELAY_US="100"
# Run broker with custom config
cargo run --release -p broker
Using a Config File¶
For more complex configurations, create a YAML file:
/tmp/felix-dev.yml:
# Network bindings
quic_bind: "0.0.0.0:5000"
metrics_bind: "0.0.0.0:8080"
# Optional control plane
controlplane_url: "http://localhost:8443"
controlplane_sync_interval_ms: 2000
# Publishing behavior
ack_on_commit: false
max_frame_bytes: 16777216 # 16 MiB
# Timeouts
publish_queue_wait_timeout_ms: 2000
ack_wait_timeout_ms: 2000
control_stream_drain_timeout_ms: 50
# Cache flow control
cache_conn_recv_window: 268435456 # 256 MiB
cache_stream_recv_window: 67108864 # 64 MiB
cache_send_window: 268435456 # 256 MiB
# Event batching
event_batch_max_events: 64
event_batch_max_bytes: 65536 # 64 KiB
event_batch_max_delay_us: 250
# Fanout and workers
fanout_batch_size: 64
pub_workers_per_conn: 4
pub_queue_depth: 1024
subscriber_queue_capacity: 128
subscriber_writer_lanes: 4
subscriber_lane_queue_depth: 8192
max_subscriber_writer_lanes: 8
subscriber_lane_shard: auto
# Performance
disable_timings: false
Run with custom config:
Config File Priority
If FELIX_BROKER_CONFIG is set and the file doesn't exist, the broker will fail to start. Without this variable, the broker looks for /usr/local/felix/config.yml but continues with defaults if not found.
Common Development Scenarios¶
Scenario 1: Low-Latency Testing¶
Optimize for minimum latency (single subscriber, small batches):
export FELIX_EVENT_BATCH_MAX_DELAY_US="50"
export FELIX_EVENT_BATCH_MAX_EVENTS="1"
export FELIX_FANOUT_BATCH="1"
export FELIX_DISABLE_TIMINGS="1"
cargo run --release -p broker
Scenario 2: High-Throughput Testing¶
Optimize for maximum throughput (large batches, higher fanout):
export FELIX_EVENT_BATCH_MAX_DELAY_US="1000"
export FELIX_EVENT_BATCH_MAX_EVENTS="256"
export FELIX_EVENT_BATCH_MAX_BYTES="1048576" # 1 MiB
export FELIX_FANOUT_BATCH="128"
cargo run --release -p broker
Scenario 3: Multi-Client Development¶
Run multiple clients connecting to the same broker:
# Terminal 1: Start broker
cargo run --release -p broker
# Terminal 2: Run subscriber demo
cargo run --release -p broker --bin pubsub-demo-simple
# Terminal 3: Run another client
cargo run --release -p broker --bin cache-demo
Scenario 4: Testing Control Plane Integration¶
Set up broker to connect to a local control plane:
export FELIX_CONTROLPLANE_URL="http://localhost:8443"
export FELIX_CONTROLPLANE_SYNC_INTERVAL_MS="1000"
cargo run --release -p broker
Performance Profiles¶
Felix includes pre-tuned performance profiles for different use cases:
Balanced Profile (Default)¶
Good starting point for mixed workloads:
export FELIX_EVENT_CONN_POOL="8"
export FELIX_EVENT_CONN_RECV_WINDOW="268435456"
export FELIX_EVENT_STREAM_RECV_WINDOW="67108864"
export FELIX_EVENT_SEND_WINDOW="268435456"
export FELIX_EVENT_BATCH_MAX_DELAY_US="250"
export FELIX_CACHE_CONN_POOL="8"
export FELIX_CACHE_STREAMS_PER_CONN="4"
cargo run --release -p broker
High-Memory Profile¶
For burst tolerance with more memory:
export FELIX_EVENT_CONN_POOL="8"
export FELIX_EVENT_CONN_RECV_WINDOW="536870912" # 512 MiB
export FELIX_EVENT_STREAM_RECV_WINDOW="134217728" # 128 MiB
export FELIX_EVENT_SEND_WINDOW="536870912" # 512 MiB
export FELIX_EVENT_BATCH_MAX_DELAY_US="250"
export FELIX_CACHE_CONN_POOL="8"
export FELIX_CACHE_STREAMS_PER_CONN="4"
export FELIX_DISABLE_TIMINGS="1"
cargo run --release -p broker
Memory vs Performance
Larger window sizes allow absorbing traffic bursts without flow-control stalls, but multiply memory usage with connection pools. Monitor actual RSS to understand memory pressure.
Running Demos¶
Felix includes several demonstration programs:
Self-contained demos
The demo binaries start an in-process broker and QUIC server on a random local port. You do not need to run the broker separately for these demos.
Pub/Sub Demo¶
Demonstrates: - Subscribing to a stream - Publishing messages - Receiving events with fanout
Cache Demo¶
Benchmarks cache operations:
- put with TTL
- get_hit (key exists)
- get_miss (key doesn't exist)
Latency Demo¶
# Basic run
cargo run --release -p broker --bin latency-demo
# Custom configuration
cargo run --release -p broker --bin latency-demo -- \
--binary \
--fanout 10 \
--batch 64 \
--payload 4096 \
--total 10000 \
--warmup 500
Parameters:
--binary: Use binary batch encoding (higher throughput)--fanout N: Number of concurrent subscribers--batch N: Messages per batch--payload N: Payload size in bytes--total N: Total messages to publish--warmup N: Warmup messages before measurement
Scenario Demos¶
Notifications (Multi-tenant alerts)¶
Optional flags: --alerts=10, --last-n=5, --drop-subscriber.
Orders/Payments Pipeline¶
Optional flags: --orders=12, --duplicate-every=5, --kill-worker=payments.
Live RBAC Policy Change¶
Demonstrates live RBAC updates via the control plane with real token exchange and broker authorization. Uses an in-memory control-plane store (no Postgres required).
Cross-Tenant Isolation¶
Demonstrates that tokens minted for one tenant cannot access another tenant's
resources, even when the same upstream identity is used.
Uses a Postgres-backed control plane (requires task pg:up or an external DB).
Using Task Commands¶
If you have Task installed:
# Build workspace
task build
# Run tests
task test
# Run linter
task lint
# Format code
task fmt
# Run demos
task demo:pubsub
task demo:cache
task demo:latency
task demo:notifications
task demo:orders
task demo:rbac-live
task demo:cross-tenant-isolation
# Run conformance tests
task conformance
# Generate coverage report
task coverage
See Taskfile.yml for all available tasks.
Monitoring Local Development¶
Metrics Endpoint¶
The broker exposes metrics on the HTTP port:
# Health check
curl http://localhost:8080/healthz
# Prometheus metrics (if enabled)
curl http://localhost:8080/metrics
Structured Logging¶
Felix logs in structured format to stdout:
2026-01-25T10:00:01.123Z INFO felix_broker: Connection accepted remote_addr=127.0.0.1:54321
2026-01-25T10:00:01.456Z INFO felix_broker: Subscription created tenant=dev namespace=test stream=events
2026-01-25T10:00:02.789Z WARN felix_broker: Publish queue pressure queue_depth=512
Control log verbosity with RUST_LOG:
# Debug level (verbose)
export RUST_LOG="debug"
# Info level (default)
export RUST_LOG="info"
# Specific module
export RUST_LOG="felix_broker=debug,felix_wire=trace"
cargo run --release -p broker
Troubleshooting¶
Port Already in Use¶
Error: Address already in use (os error 48)
Solution: Change the ports:
Build Failures¶
Error: Compilation errors or missing dependencies
Solution: Ensure correct Rust version:
Connection Refused¶
Error: Client cannot connect to broker
Solution: Verify broker is running and listening:
# Check processes
ps aux | grep broker
# Check UDP listener
lsof -i UDP:5000
# Check logs
RUST_LOG=debug cargo run --release -p broker
High Memory Usage¶
Issue: Broker consuming excessive memory
Solution: Reduce window sizes:
export FELIX_EVENT_CONN_RECV_WINDOW="134217728" # 128 MiB
export FELIX_EVENT_STREAM_RECV_WINDOW="33554432" # 32 MiB
export FELIX_CACHE_CONN_RECV_WINDOW="134217728"
Slow Performance¶
Issue: Unexpectedly high latency
Solution:
- Use release builds: Debug builds are 10-100x slower
- Disable timings:
export FELIX_DISABLE_TIMINGS="1" - Check batching: Increase batch sizes for throughput
- Profile with
perf: Identify hot paths
Next Steps¶
- Learn the client API: Client SDK Guide
- Deploy with Docker: Docker Compose Setup
- Production deployment: Kubernetes Guide
- Tune performance: Performance Guide
- Configure fully: Configuration Reference