QuickDID is a high-performance AT Protocol identity resolution service written in Rust. It provides handle-to-DID resolution with Redis-backed caching and queue processing.
1# QuickDID Configuration Reference 2 3This document provides a comprehensive reference for all configuration options available in QuickDID. 4 5## Table of Contents 6 7- [Required Configuration](#required-configuration) 8- [Network Configuration](#network-configuration) 9- [Caching Configuration](#caching-configuration) 10- [Queue Configuration](#queue-configuration) 11- [Rate Limiting Configuration](#rate-limiting-configuration) 12- [HTTP Caching Configuration](#http-caching-configuration) 13- [Metrics Configuration](#metrics-configuration) 14- [Proactive Refresh Configuration](#proactive-refresh-configuration) 15- [Jetstream Consumer Configuration](#jetstream-consumer-configuration) 16- [Static Files Configuration](#static-files-configuration) 17- [Configuration Examples](#configuration-examples) 18- [Validation Rules](#validation-rules) 19 20## Required Configuration 21 22These environment variables MUST be set for QuickDID to start. 23 24### `HTTP_EXTERNAL` 25 26**Required**: Yes 27**Type**: String 28**Format**: Hostname with optional port 29 30The external hostname where this service will be accessible. This is used to generate the service DID and for AT Protocol identity resolution. 31 32**Examples**: 33```bash 34# Production domain 35HTTP_EXTERNAL=quickdid.example.com 36 37# With non-standard port 38HTTP_EXTERNAL=quickdid.example.com:8080 39 40# Development/testing 41HTTP_EXTERNAL=localhost:3007 42``` 43 44**Constraints**: 45- Must be a valid hostname or hostname:port combination 46- Port (if specified) must be between 1-65535 47 48## Network Configuration 49 50### `HTTP_PORT` 51 52**Required**: No 53**Type**: String 54**Default**: `8080` 55**Range**: 1-65535 56 57The port number for the HTTP server to bind to. 58 59**Examples**: 60```bash 61HTTP_PORT=8080 # Default 62HTTP_PORT=3000 # Common alternative 63HTTP_PORT=80 # Standard HTTP (requires root/privileges) 64``` 65 66### `PLC_HOSTNAME` 67 68**Required**: No 69**Type**: String 70**Default**: `plc.directory` 71 72The hostname of the PLC directory service for DID resolution. 73 74**Examples**: 75```bash 76PLC_HOSTNAME=plc.directory # Production (default) 77PLC_HOSTNAME=test.plc.directory # Testing environment 78PLC_HOSTNAME=localhost:2582 # Local PLC server 79``` 80 81### `DNS_NAMESERVERS` 82 83**Required**: No 84**Type**: String (comma-separated IP addresses) 85**Default**: System DNS 86 87Custom DNS nameservers for handle resolution via TXT records. 88 89**Examples**: 90```bash 91# Google DNS 92DNS_NAMESERVERS=8.8.8.8,8.8.4.4 93 94# Cloudflare DNS 95DNS_NAMESERVERS=1.1.1.1,1.0.0.1 96 97# Multiple providers 98DNS_NAMESERVERS=8.8.8.8,1.1.1.1 99 100# Local DNS 101DNS_NAMESERVERS=192.168.1.1 102``` 103 104### `USER_AGENT` 105 106**Required**: No 107**Type**: String 108**Default**: `quickdid/{version} (+https://github.com/smokesignal.events/quickdid)` 109 110HTTP User-Agent header for outgoing requests. 111 112**Examples**: 113```bash 114# Custom agent 115USER_AGENT="MyService/1.0.0 (+https://myservice.com)" 116 117# With contact info 118USER_AGENT="quickdid/1.0.0 (+https://quickdid.example.com; admin@example.com)" 119``` 120 121### `CERTIFICATE_BUNDLES` 122 123**Required**: No 124**Type**: String (comma-separated file paths) 125**Default**: System CA certificates 126 127Additional CA certificate bundles for TLS connections. 128 129**Examples**: 130```bash 131# Single certificate 132CERTIFICATE_BUNDLES=/etc/ssl/certs/custom-ca.pem 133 134# Multiple certificates 135CERTIFICATE_BUNDLES=/certs/ca1.pem,/certs/ca2.pem 136 137# Corporate CA 138CERTIFICATE_BUNDLES=/usr/local/share/ca-certificates/corporate-ca.crt 139``` 140 141## Caching Configuration 142 143### `REDIS_URL` 144 145**Required**: No (recommended for multi-instance production) 146**Type**: String 147**Format**: Redis connection URL 148 149Redis connection URL for persistent caching. Enables distributed caching and better performance. 150 151**Examples**: 152```bash 153# Local Redis (no auth) 154REDIS_URL=redis://localhost:6379/0 155 156# With authentication 157REDIS_URL=redis://user:password@redis.example.com:6379/0 158 159# Using database 1 160REDIS_URL=redis://localhost:6379/1 161 162# Redis Sentinel 163REDIS_URL=redis-sentinel://sentinel1:26379,sentinel2:26379/mymaster/0 164 165# TLS connection 166REDIS_URL=rediss://secure-redis.example.com:6380/0 167``` 168 169### `SQLITE_URL` 170 171**Required**: No (recommended for single-instance production) 172**Type**: String 173**Format**: SQLite database URL 174 175SQLite database URL for persistent caching. Provides single-file persistent storage without external dependencies. 176 177**Examples**: 178```bash 179# File-based database (recommended) 180SQLITE_URL=sqlite:./quickdid.db 181 182# With absolute path 183SQLITE_URL=sqlite:/var/lib/quickdid/cache.db 184 185# In-memory database (testing only) 186SQLITE_URL=sqlite::memory: 187 188# Alternative file syntax 189SQLITE_URL=sqlite:///path/to/database.db 190``` 191 192**Cache Priority**: QuickDID uses the first available cache: 1931. Redis (if `REDIS_URL` is configured) 1942. SQLite (if `SQLITE_URL` is configured) 1953. In-memory cache (fallback) 196 197### `CACHE_TTL_MEMORY` 198 199**Required**: No 200**Type**: Integer (seconds) 201**Default**: `600` (10 minutes) 202**Range**: 60-3600 (recommended) 203**Constraints**: Must be > 0 204 205Time-to-live for in-memory cache entries in seconds. Used when Redis is not available. 206 207**Examples**: 208```bash 209CACHE_TTL_MEMORY=300 # 5 minutes (aggressive refresh) 210CACHE_TTL_MEMORY=600 # 10 minutes (default, balanced) 211CACHE_TTL_MEMORY=1800 # 30 minutes (less frequent updates) 212CACHE_TTL_MEMORY=3600 # 1 hour (stable data) 213``` 214 215**Recommendations**: 216- Lower values: Fresher data, more DNS/HTTP lookups, higher load 217- Higher values: Better performance, potentially stale data 218- Production with Redis: Can use lower values (300-600) 219- Production without Redis: Use higher values (1800-3600) 220 221### `CACHE_TTL_REDIS` 222 223**Required**: No 224**Type**: Integer (seconds) 225**Default**: `7776000` (90 days) 226**Range**: 3600-31536000 (1 hour to 1 year) 227**Constraints**: Must be > 0 228 229Time-to-live for Redis cache entries in seconds. 230 231**Examples**: 232```bash 233CACHE_TTL_REDIS=3600 # 1 hour (frequently changing data) 234CACHE_TTL_REDIS=86400 # 1 day (recommended for active handles) 235CACHE_TTL_REDIS=604800 # 1 week (balanced) 236CACHE_TTL_REDIS=2592000 # 30 days (stable handles) 237CACHE_TTL_REDIS=7776000 # 90 days (default, maximum stability) 238``` 239 240### `CACHE_TTL_SQLITE` 241 242**Required**: No 243**Type**: Integer (seconds) 244**Default**: `7776000` (90 days) 245**Range**: 3600-31536000 (1 hour to 1 year) 246**Constraints**: Must be > 0 247 248Time-to-live for SQLite cache entries in seconds. Only used when `SQLITE_URL` is configured. 249 250**Examples**: 251```bash 252CACHE_TTL_SQLITE=3600 # 1 hour (frequently changing data) 253CACHE_TTL_SQLITE=86400 # 1 day (recommended for active handles) 254CACHE_TTL_SQLITE=604800 # 1 week (balanced) 255CACHE_TTL_SQLITE=2592000 # 30 days (stable handles) 256CACHE_TTL_SQLITE=7776000 # 90 days (default, maximum stability) 257``` 258 259**TTL Recommendations**: 260- Social media handles: 1-7 days 261- Corporate/stable handles: 30-90 days 262- Test environments: 1 hour 263- Single-instance deployments: Can use longer TTLs (30-90 days) 264- Multi-instance deployments: Use shorter TTLs (1-7 days) 265 266## Queue Configuration 267 268### `QUEUE_ADAPTER` 269 270**Required**: No 271**Type**: String 272**Default**: `mpsc` 273**Values**: `mpsc`, `redis`, `sqlite`, `noop`, `none` 274 275The type of queue adapter for background handle resolution. 276 277**Options**: 278- `mpsc`: In-memory multi-producer single-consumer queue (default) 279- `redis`: Redis-backed distributed queue 280- `sqlite`: SQLite-backed persistent queue 281- `noop`: Disable queue processing (testing only) 282- `none`: Alias for `noop` 283 284**Examples**: 285```bash 286# Single instance deployment 287QUEUE_ADAPTER=mpsc 288 289# Multi-instance or high availability 290QUEUE_ADAPTER=redis 291 292# Single instance with persistence 293QUEUE_ADAPTER=sqlite 294 295# Testing without background processing 296QUEUE_ADAPTER=noop 297 298# Alternative syntax for disabling 299QUEUE_ADAPTER=none 300``` 301 302### `QUEUE_REDIS_URL` 303 304**Required**: No 305**Type**: String 306**Default**: Falls back to `REDIS_URL` 307 308Dedicated Redis URL for queue operations. Use when separating cache and queue Redis instances. 309 310**Examples**: 311```bash 312# Separate Redis for queues 313QUEUE_REDIS_URL=redis://queue-redis:6379/2 314 315# With different credentials 316QUEUE_REDIS_URL=redis://queue_user:queue_pass@redis.example.com:6379/1 317``` 318 319### `QUEUE_REDIS_PREFIX` 320 321**Required**: No 322**Type**: String 323**Default**: `queue:handleresolver:` 324 325Redis key prefix for queue operations. Use to namespace queues when sharing Redis. 326 327**Examples**: 328```bash 329# Default 330QUEUE_REDIS_PREFIX=queue:handleresolver: 331 332# Environment-specific 333QUEUE_REDIS_PREFIX=prod:queue:hr: 334QUEUE_REDIS_PREFIX=staging:queue:hr: 335 336# Version-specific 337QUEUE_REDIS_PREFIX=quickdid:v1:queue: 338 339# Instance-specific 340QUEUE_REDIS_PREFIX=us-east-1:queue:hr: 341``` 342 343### `QUEUE_REDIS_TIMEOUT` 344 345**Required**: No 346**Type**: Integer (seconds) 347**Default**: `5` 348**Range**: 1-60 (recommended) 349**Constraints**: Must be > 0 350 351Redis blocking timeout for queue operations in seconds. Controls how long to wait for new items. 352 353**Examples**: 354```bash 355QUEUE_REDIS_TIMEOUT=1 # Very responsive, more polling 356QUEUE_REDIS_TIMEOUT=5 # Default, balanced 357QUEUE_REDIS_TIMEOUT=10 # Less polling, slower shutdown 358QUEUE_REDIS_TIMEOUT=30 # Minimal polling, slow shutdown 359``` 360 361### `QUEUE_REDIS_DEDUP_ENABLED` 362 363**Required**: No 364**Type**: Boolean 365**Default**: `false` 366 367Enable deduplication for Redis queue to prevent duplicate handles from being queued multiple times within the TTL window. When enabled, uses Redis SET with TTL to track handles currently being processed. 368 369**Examples**: 370```bash 371# Enable deduplication (recommended for production) 372QUEUE_REDIS_DEDUP_ENABLED=true 373 374# Disable deduplication (default) 375QUEUE_REDIS_DEDUP_ENABLED=false 376``` 377 378**Use cases**: 379- **Production**: Enable to prevent duplicate work and reduce load 380- **High-traffic**: Essential to avoid processing the same handle multiple times 381- **Development**: Can be disabled for simpler debugging 382 383### `QUEUE_REDIS_DEDUP_TTL` 384 385**Required**: No 386**Type**: Integer (seconds) 387**Default**: `60` 388**Range**: 10-300 (recommended) 389**Constraints**: Must be > 0 when deduplication is enabled 390 391TTL for Redis queue deduplication keys in seconds. Determines how long to prevent duplicate handle resolution requests. 392 393**Examples**: 394```bash 395# Quick deduplication window (10 seconds) 396QUEUE_REDIS_DEDUP_TTL=10 397 398# Default (1 minute) 399QUEUE_REDIS_DEDUP_TTL=60 400 401# Extended deduplication (5 minutes) 402QUEUE_REDIS_DEDUP_TTL=300 403``` 404 405**Recommendations**: 406- **Fast processing**: 10-30 seconds 407- **Normal processing**: 60 seconds (default) 408- **Slow processing or high load**: 120-300 seconds 409 410### `QUEUE_WORKER_ID` 411 412**Required**: No 413**Type**: String 414**Default**: `worker1` 415 416Worker identifier for queue operations. Used in logs and monitoring. 417 418**Examples**: 419```bash 420# Simple numbering 421QUEUE_WORKER_ID=worker-001 422 423# Environment-based 424QUEUE_WORKER_ID=prod-us-east-1 425QUEUE_WORKER_ID=staging-worker-2 426 427# Hostname-based 428QUEUE_WORKER_ID=$(hostname) 429 430# Pod name in Kubernetes 431QUEUE_WORKER_ID=$HOSTNAME 432``` 433 434### `QUEUE_BUFFER_SIZE` 435 436**Required**: No 437**Type**: Integer 438**Default**: `1000` 439**Range**: 100-100000 (recommended) 440 441Buffer size for the MPSC queue adapter. Only used when `QUEUE_ADAPTER=mpsc`. 442 443**Examples**: 444```bash 445QUEUE_BUFFER_SIZE=100 # Minimal memory, may block 446QUEUE_BUFFER_SIZE=1000 # Default, balanced 447QUEUE_BUFFER_SIZE=5000 # High traffic 448QUEUE_BUFFER_SIZE=10000 # Very high traffic 449``` 450 451### `QUEUE_SQLITE_MAX_SIZE` 452 453**Required**: No 454**Type**: Integer 455**Default**: `10000` 456**Range**: 100-1000000 (recommended) 457**Constraints**: Must be >= 0 458 459Maximum queue size for SQLite adapter work shedding. When the queue exceeds this limit, the oldest entries are automatically deleted to maintain the specified size limit, preserving the most recently queued work items. 460 461**Work Shedding Behavior**: 462- New work items are always accepted 463- When queue size exceeds `QUEUE_SQLITE_MAX_SIZE`, oldest entries are deleted 464- Deletion happens atomically with insertion in a single transaction 465- Essential for long-running deployments to prevent unbounded disk growth 466- Set to `0` to disable work shedding (unlimited queue size) 467 468**Examples**: 469```bash 470QUEUE_SQLITE_MAX_SIZE=0 # Unlimited (disable work shedding) 471QUEUE_SQLITE_MAX_SIZE=1000 # Small deployment, frequent processing 472QUEUE_SQLITE_MAX_SIZE=10000 # Default, balanced for most deployments 473QUEUE_SQLITE_MAX_SIZE=100000 # High-traffic deployment with slower processing 474QUEUE_SQLITE_MAX_SIZE=1000000 # Very high-traffic, maximum recommended 475``` 476 477**Recommendations**: 478- **Small deployments**: 1000-5000 entries 479- **Production deployments**: 10000-50000 entries 480- **High-traffic deployments**: 50000-1000000 entries 481- **Development/testing**: 100-1000 entries 482- **Disk space concerns**: Lower values (1000-5000) 483- **High ingestion rate**: Higher values (50000-1000000) 484 485## Rate Limiting Configuration 486 487### `RESOLVER_MAX_CONCURRENT` 488 489**Required**: No 490**Type**: Integer 491**Default**: `0` (disabled) 492**Range**: 0-10000 493**Constraints**: Must be between 0 and 10000 494 495Maximum concurrent handle resolutions allowed. When set to a value greater than 0, enables semaphore-based rate limiting to protect upstream DNS and HTTP services from being overwhelmed. 496 497**How it works**: 498- Uses a semaphore to limit concurrent resolutions 499- Applied between the base resolver and caching layers 500- Requests wait for an available permit before resolution 501- Helps prevent overwhelming upstream services 502 503**Examples**: 504```bash 505# Disabled (default) 506RESOLVER_MAX_CONCURRENT=0 507 508# Light rate limiting 509RESOLVER_MAX_CONCURRENT=10 510 511# Moderate rate limiting 512RESOLVER_MAX_CONCURRENT=50 513 514# Heavy traffic with rate limiting 515RESOLVER_MAX_CONCURRENT=100 516 517# Maximum allowed 518RESOLVER_MAX_CONCURRENT=10000 519``` 520 521**Recommendations**: 522- **Development**: 0 (disabled) or 10-50 for testing 523- **Production (low traffic)**: 50-100 524- **Production (high traffic)**: 100-500 525- **Production (very high traffic)**: 500-1000 526- **Testing rate limiting**: 1-5 to observe behavior 527 528**Placement in resolver stack**: 529``` 530Request → Cache → RateLimited → Base → DNS/HTTP 531``` 532 533### `RESOLVER_MAX_CONCURRENT_TIMEOUT_MS` 534 535**Required**: No 536**Type**: Integer (milliseconds) 537**Default**: `0` (no timeout) 538**Range**: 0-60000 539**Constraints**: Must be between 0 and 60000 (60 seconds max) 540 541Timeout for acquiring a rate limit permit in milliseconds. When set to a value greater than 0, requests will timeout if they cannot acquire a permit within the specified time, preventing them from waiting indefinitely when the rate limiter is at capacity. 542 543**How it works**: 544- Applied when `RESOLVER_MAX_CONCURRENT` is enabled (> 0) 545- Uses `tokio::time::timeout` to limit permit acquisition time 546- Returns an error if timeout expires before permit is acquired 547- Prevents request queue buildup during high load 548 549**Examples**: 550```bash 551# No timeout (default) 552RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=0 553 554# Quick timeout for responsive failures (100ms) 555RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=100 556 557# Moderate timeout (1 second) 558RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=1000 559 560# Longer timeout for production (5 seconds) 561RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=5000 562 563# Maximum allowed (60 seconds) 564RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=60000 565``` 566 567**Recommendations**: 568- **Development**: 100-1000ms for quick feedback 569- **Production (low latency)**: 1000-5000ms 570- **Production (high latency tolerance)**: 5000-30000ms 571- **Testing**: 100ms to quickly identify bottlenecks 572- **0**: Use when you want requests to wait indefinitely 573 574**Error behavior**: 575When a timeout occurs, the request fails with: 576``` 577Rate limit permit acquisition timed out after {timeout}ms 578``` 579 580## Metrics Configuration 581 582### `METRICS_ADAPTER` 583 584**Required**: No 585**Type**: String 586**Default**: `noop` 587**Values**: `noop`, `statsd` 588 589Metrics adapter type for collecting and publishing metrics. 590 591**Options**: 592- `noop`: No metrics collection (default) 593- `statsd`: Send metrics to StatsD server 594 595**Examples**: 596```bash 597# No metrics (default) 598METRICS_ADAPTER=noop 599 600# Enable StatsD metrics 601METRICS_ADAPTER=statsd 602``` 603 604### `METRICS_STATSD_HOST` 605 606**Required**: Yes (when METRICS_ADAPTER=statsd) 607**Type**: String 608**Format**: hostname:port 609 610StatsD server host and port for metrics collection. 611 612**Examples**: 613```bash 614# Local StatsD 615METRICS_STATSD_HOST=localhost:8125 616 617# Remote StatsD 618METRICS_STATSD_HOST=statsd.example.com:8125 619 620# Docker network 621METRICS_STATSD_HOST=statsd:8125 622``` 623 624### `METRICS_STATSD_BIND` 625 626**Required**: No 627**Type**: String 628**Default**: `[::]:0` 629 630Bind address for StatsD UDP socket. Controls which local address to bind for sending UDP packets. 631 632**Examples**: 633```bash 634# IPv6 any address, random port (default) 635METRICS_STATSD_BIND=[::]:0 636 637# IPv4 any address, random port 638METRICS_STATSD_BIND=0.0.0.0:0 639 640# Specific interface 641METRICS_STATSD_BIND=192.168.1.100:0 642 643# Specific port 644METRICS_STATSD_BIND=[::]:8126 645``` 646 647### `METRICS_PREFIX` 648 649**Required**: No 650**Type**: String 651**Default**: `quickdid` 652 653Prefix for all metrics. Used to namespace metrics in your monitoring system. 654 655**Examples**: 656```bash 657# Default 658METRICS_PREFIX=quickdid 659 660# Environment-specific 661METRICS_PREFIX=prod.quickdid 662METRICS_PREFIX=staging.quickdid 663 664# Region-specific 665METRICS_PREFIX=us-east-1.quickdid 666METRICS_PREFIX=eu-west-1.quickdid 667 668# Service-specific 669METRICS_PREFIX=api.quickdid 670``` 671 672### `METRICS_TAGS` 673 674**Required**: No 675**Type**: String (comma-separated key:value pairs) 676**Default**: None 677 678Default tags for all metrics. Added to all metrics for filtering and grouping. 679 680**Examples**: 681```bash 682# Basic tags 683METRICS_TAGS=env:production,service:quickdid 684 685# Detailed tags 686METRICS_TAGS=env:production,service:quickdid,region:us-east-1,version:1.0.0 687 688# Deployment-specific 689METRICS_TAGS=env:staging,cluster:k8s-staging,namespace:quickdid 690``` 691 692**Common tag patterns**: 693- `env`: Environment (production, staging, development) 694- `service`: Service name 695- `region`: Geographic region 696- `version`: Application version 697- `cluster`: Kubernetes cluster name 698- `instance`: Instance identifier 699 700## Proactive Refresh Configuration 701 702### `PROACTIVE_REFRESH_ENABLED` 703 704**Required**: No 705**Type**: Boolean 706**Default**: `false` 707 708Enable proactive cache refresh for frequently accessed handles. When enabled, cache entries that have reached the refresh threshold will be queued for background refresh to keep the cache warm. 709 710**Examples**: 711```bash 712# Enable proactive refresh (recommended for production) 713PROACTIVE_REFRESH_ENABLED=true 714 715# Disable proactive refresh (default) 716PROACTIVE_REFRESH_ENABLED=false 717``` 718 719**Benefits**: 720- Prevents cache misses for popular handles 721- Maintains consistent response times 722- Reduces latency spikes during cache expiration 723 724**Considerations**: 725- Increases background processing load 726- More DNS/HTTP requests to upstream services 727- Best for high-traffic services with predictable access patterns 728 729### `PROACTIVE_REFRESH_THRESHOLD` 730 731**Required**: No 732**Type**: Float 733**Default**: `0.8` 734**Range**: 0.0-1.0 735**Constraints**: Must be between 0.0 and 1.0 736 737Threshold as a percentage (0.0-1.0) of cache TTL when to trigger proactive refresh. For example, 0.8 means refresh when an entry has lived for 80% of its TTL. 738 739**Examples**: 740```bash 741# Very aggressive (refresh at 50% of TTL) 742PROACTIVE_REFRESH_THRESHOLD=0.5 743 744# Moderate (refresh at 70% of TTL) 745PROACTIVE_REFRESH_THRESHOLD=0.7 746 747# Default (refresh at 80% of TTL) 748PROACTIVE_REFRESH_THRESHOLD=0.8 749 750# Conservative (refresh at 90% of TTL) 751PROACTIVE_REFRESH_THRESHOLD=0.9 752 753# Very conservative (refresh at 95% of TTL) 754PROACTIVE_REFRESH_THRESHOLD=0.95 755``` 756 757**Recommendations**: 758- **High-traffic services**: 0.5-0.7 (aggressive refresh) 759- **Normal traffic**: 0.8 (default, balanced) 760- **Low traffic**: 0.9-0.95 (conservative) 761- **Development**: 0.5 (test refresh behavior) 762 763**Impact on different cache TTLs**: 764- TTL=600s (10 min), threshold=0.8: Refresh after 8 minutes 765- TTL=3600s (1 hour), threshold=0.8: Refresh after 48 minutes 766- TTL=86400s (1 day), threshold=0.8: Refresh after 19.2 hours 767 768## Jetstream Consumer Configuration 769 770### `JETSTREAM_ENABLED` 771 772**Required**: No 773**Type**: Boolean 774**Default**: `false` 775 776Enable Jetstream consumer for real-time cache updates from the AT Protocol firehose. When enabled, QuickDID connects to the Jetstream WebSocket service to receive live updates about account and identity changes. 777 778**How it works**: 779- Subscribes to Account and Identity events from the firehose 780- Processes Account events to purge deleted/deactivated accounts 781- Processes Identity events to update handle-to-DID mappings 782- Automatically reconnects with exponential backoff on connection failures 783- Tracks metrics for successful and failed event processing 784 785**Examples**: 786```bash 787# Enable Jetstream consumer (recommended for production) 788JETSTREAM_ENABLED=true 789 790# Disable Jetstream consumer (default) 791JETSTREAM_ENABLED=false 792``` 793 794**Benefits**: 795- Real-time cache synchronization with AT Protocol network 796- Automatic removal of deleted/deactivated accounts 797- Immediate handle change updates 798- Reduces stale data in cache 799 800**Considerations**: 801- Requires stable WebSocket connection 802- Increases network traffic (incoming events) 803- Best for services requiring up-to-date handle mappings 804- Automatically handles reconnection on failures 805 806### `JETSTREAM_HOSTNAME` 807 808**Required**: No 809**Type**: String 810**Default**: `jetstream.atproto.tools` 811 812The hostname of the Jetstream WebSocket service to connect to for real-time AT Protocol events. Only used when `JETSTREAM_ENABLED=true`. 813 814**Examples**: 815```bash 816# Production firehose (default) 817JETSTREAM_HOSTNAME=jetstream.atproto.tools 818 819# Staging environment 820JETSTREAM_HOSTNAME=jetstream-staging.atproto.tools 821 822# Local development firehose 823JETSTREAM_HOSTNAME=localhost:6008 824 825# Custom deployment 826JETSTREAM_HOSTNAME=jetstream.example.com 827``` 828 829**Event Processing**: 830- **Account events**: 831 - `status: deleted` → Purges handle and DID from all caches 832 - `status: deactivated` → Purges handle and DID from all caches 833 - Other statuses → Ignored 834 835- **Identity events**: 836 - Updates handle-to-DID mapping in cache 837 - Removes old handle mapping if changed 838 - Maintains bidirectional cache consistency 839 840**Metrics Tracked** (when metrics are enabled): 841- `jetstream.events.received`: Total events received 842- `jetstream.events.processed`: Successfully processed events 843- `jetstream.events.failed`: Failed event processing 844- `jetstream.connections.established`: Successful connections 845- `jetstream.connections.failed`: Failed connection attempts 846 847**Reconnection Behavior**: 848- Initial retry delay: 1 second 849- Maximum retry delay: 60 seconds 850- Exponential backoff with jitter 851- Automatic recovery on transient failures 852 853**Recommendations**: 854- **Production**: Use default `jetstream.atproto.tools` 855- **Development**: Consider local firehose for testing 856- **High availability**: Monitor connection metrics 857- **Network issues**: Check WebSocket connectivity 858 859## Static Files Configuration 860 861### `STATIC_FILES_DIR` 862 863**Required**: No 864**Type**: String (directory path) 865**Default**: `www` 866 867Directory path for serving static files. This directory should contain the landing page and AT Protocol well-known files. 868 869**Directory Structure**: 870``` 871www/ 872├── index.html # Landing page 873├── .well-known/ 874│ ├── atproto-did # Service DID identifier 875│ └── did.json # DID document 876└── (other static assets) 877``` 878 879**Examples**: 880```bash 881# Default (relative to working directory) 882STATIC_FILES_DIR=www 883 884# Absolute path 885STATIC_FILES_DIR=/var/www/quickdid 886 887# Docker container path 888STATIC_FILES_DIR=/app/www 889 890# Custom directory 891STATIC_FILES_DIR=./public 892``` 893 894**Docker Volume Mounting**: 895```yaml 896volumes: 897 # Mount entire custom directory 898 - ./custom-www:/app/www:ro 899 900 # Mount specific files 901 - ./custom-index.html:/app/www/index.html:ro 902 - ./well-known:/app/www/.well-known:ro 903``` 904 905**Generating Well-Known Files**: 906```bash 907# Generate .well-known files for your domain 908HTTP_EXTERNAL=your-domain.com ./generate-wellknown.sh 909``` 910 911## HTTP Caching Configuration 912 913### `CACHE_MAX_AGE` 914 915**Required**: No 916**Type**: Integer (seconds) 917**Default**: `86400` (24 hours) 918**Range**: 0-31536000 (0 to 1 year) 919 920Maximum age for HTTP Cache-Control header in seconds. When set to 0, the Cache-Control header is disabled and will not be added to responses. This controls how long clients and intermediate caches can cache responses. 921 922**Examples**: 923```bash 924# Default (24 hours) 925CACHE_MAX_AGE=86400 926 927# Aggressive caching (7 days) 928CACHE_MAX_AGE=604800 929 930# Conservative caching (1 hour) 931CACHE_MAX_AGE=3600 932 933# Disable Cache-Control header 934CACHE_MAX_AGE=0 935``` 936 937### `CACHE_STALE_IF_ERROR` 938 939**Required**: No 940**Type**: Integer (seconds) 941**Default**: `172800` (48 hours) 942 943Allows stale content to be served if the backend encounters an error. This provides resilience during service outages. 944 945**Examples**: 946```bash 947# Default (48 hours) 948CACHE_STALE_IF_ERROR=172800 949 950# Extended error tolerance (7 days) 951CACHE_STALE_IF_ERROR=604800 952 953# Minimal error tolerance (1 hour) 954CACHE_STALE_IF_ERROR=3600 955``` 956 957### `CACHE_STALE_WHILE_REVALIDATE` 958 959**Required**: No 960**Type**: Integer (seconds) 961**Default**: `86400` (24 hours) 962 963Allows stale content to be served while fresh content is being fetched in the background. This improves perceived performance. 964 965**Examples**: 966```bash 967# Default (24 hours) 968CACHE_STALE_WHILE_REVALIDATE=86400 969 970# Quick revalidation (1 hour) 971CACHE_STALE_WHILE_REVALIDATE=3600 972 973# Extended revalidation (7 days) 974CACHE_STALE_WHILE_REVALIDATE=604800 975``` 976 977### `CACHE_MAX_STALE` 978 979**Required**: No 980**Type**: Integer (seconds) 981**Default**: `172800` (48 hours) 982 983Maximum time a client will accept stale responses. This provides an upper bound on how old cached content can be. 984 985**Examples**: 986```bash 987# Default (48 hours) 988CACHE_MAX_STALE=172800 989 990# Extended staleness (7 days) 991CACHE_MAX_STALE=604800 992 993# Strict freshness (1 hour) 994CACHE_MAX_STALE=3600 995``` 996 997### `CACHE_MIN_FRESH` 998 999**Required**: No 1000**Type**: Integer (seconds) 1001**Default**: `3600` (1 hour) 1002 1003Minimum time a response must remain fresh. Clients will not accept responses that will expire within this time. 1004 1005**Examples**: 1006```bash 1007# Default (1 hour) 1008CACHE_MIN_FRESH=3600 1009 1010# Strict freshness (24 hours) 1011CACHE_MIN_FRESH=86400 1012 1013# Relaxed freshness (5 minutes) 1014CACHE_MIN_FRESH=300 1015``` 1016 1017**Cache-Control Header Format**: 1018 1019When `CACHE_MAX_AGE` is greater than 0, the following Cache-Control header is added to responses: 1020``` 1021Cache-Control: public, max-age=86400, stale-while-revalidate=86400, stale-if-error=172800, max-stale=172800, min-fresh=3600 1022``` 1023 1024**Recommendations**: 1025- **High-traffic services**: Use longer max-age (86400-604800) to reduce load 1026- **Frequently changing data**: Use shorter max-age (3600-14400) 1027- **Critical services**: Set higher stale-if-error for resilience 1028- **Performance-sensitive**: Enable stale-while-revalidate for better UX 1029- **Disable caching**: Set CACHE_MAX_AGE=0 for real-time data 1030 1031### `ETAG_SEED` 1032 1033**Required**: No 1034**Type**: String 1035**Default**: Application version (from `CARGO_PKG_VERSION`) 1036 1037Seed value for ETAG generation to allow cache invalidation. This value is incorporated into ETAG checksums, allowing server administrators to invalidate client-cached responses after major changes or deployments. 1038 1039**How it works**: 1040- Combined with response content to generate ETAG checksums 1041- Uses MetroHash64 for fast, non-cryptographic hashing 1042- Generates weak ETags (W/"hash") for HTTP caching 1043- Changing the seed invalidates all client caches 1044 1045**Examples**: 1046```bash 1047# Default (uses application version) 1048# ETAG_SEED is automatically set to the version 1049 1050# Deployment-specific seed 1051ETAG_SEED=prod-2024-01-15 1052 1053# Version with timestamp 1054ETAG_SEED=v1.0.0-1705344000 1055 1056# Environment-specific 1057ETAG_SEED=staging-v2 1058 1059# Force cache invalidation after config change 1060ETAG_SEED=config-update-2024-01-15 1061``` 1062 1063**Use cases**: 1064- **Major configuration changes**: Update seed to invalidate all cached responses 1065- **Data migration**: Force clients to refetch after backend changes 1066- **Security updates**: Ensure clients get fresh data after security fixes 1067- **A/B testing**: Different seeds for different deployment groups 1068- **Rollback scenarios**: Revert to previous seed to restore cache behavior 1069 1070**Recommendations**: 1071- **Default**: Use the application version (automatic) 1072- **Production**: Include deployment date or config version 1073- **Staging**: Use environment-specific seeds 1074- **After incidents**: Update seed to force fresh data 1075- **Routine deployments**: Keep the same seed if no data changes 1076 1077## Configuration Examples 1078 1079### Minimal Development Configuration 1080 1081```bash 1082# .env.development 1083HTTP_EXTERNAL=localhost:3007 1084RUST_LOG=debug 1085``` 1086 1087### Standard Production Configuration (Redis) 1088 1089```bash 1090# .env.production.redis 1091# Required 1092HTTP_EXTERNAL=quickdid.example.com 1093 1094# Network 1095HTTP_PORT=8080 1096USER_AGENT=quickdid/1.0.0 (+https://quickdid.example.com) 1097 1098# Caching (Redis-based) 1099REDIS_URL=redis://redis:6379/0 1100CACHE_TTL_MEMORY=600 1101CACHE_TTL_REDIS=86400 # 1 day 1102 1103# Queue 1104QUEUE_ADAPTER=redis 1105QUEUE_REDIS_TIMEOUT=5 1106QUEUE_BUFFER_SIZE=5000 1107QUEUE_REDIS_DEDUP_ENABLED=true # Prevent duplicate work 1108QUEUE_REDIS_DEDUP_TTL=60 1109 1110# Rate Limiting (optional, recommended for production) 1111RESOLVER_MAX_CONCURRENT=100 1112RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=5000 # 5 second timeout 1113 1114# Metrics (optional, recommended for production) 1115METRICS_ADAPTER=statsd 1116METRICS_STATSD_HOST=localhost:8125 1117METRICS_PREFIX=quickdid 1118METRICS_TAGS=env:prod,service:quickdid 1119 1120# Proactive Refresh (optional, recommended for high-traffic) 1121PROACTIVE_REFRESH_ENABLED=true 1122PROACTIVE_REFRESH_THRESHOLD=0.8 1123 1124# Jetstream Consumer (optional, recommended for real-time sync) 1125JETSTREAM_ENABLED=true 1126JETSTREAM_HOSTNAME=jetstream.atproto.tools 1127 1128# HTTP Caching (Cache-Control headers) 1129CACHE_MAX_AGE=86400 # 24 hours 1130CACHE_STALE_IF_ERROR=172800 # 48 hours 1131CACHE_STALE_WHILE_REVALIDATE=86400 # 24 hours 1132 1133# Logging 1134RUST_LOG=info 1135``` 1136 1137### Standard Production Configuration (SQLite) 1138 1139```bash 1140# .env.production.sqlite 1141# Required 1142HTTP_EXTERNAL=quickdid.example.com 1143 1144# Network 1145HTTP_PORT=8080 1146USER_AGENT=quickdid/1.0.0 (+https://quickdid.example.com) 1147 1148# Caching (SQLite-based for single instance) 1149SQLITE_URL=sqlite:/data/quickdid.db 1150CACHE_TTL_MEMORY=600 1151CACHE_TTL_SQLITE=86400 # 1 day 1152 1153# Queue (SQLite for single instance with persistence) 1154QUEUE_ADAPTER=sqlite 1155QUEUE_BUFFER_SIZE=5000 1156QUEUE_SQLITE_MAX_SIZE=10000 1157 1158# Rate Limiting (optional, recommended for production) 1159RESOLVER_MAX_CONCURRENT=100 1160RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=5000 # 5 second timeout 1161 1162# Jetstream Consumer (optional, recommended for real-time sync) 1163JETSTREAM_ENABLED=true 1164JETSTREAM_HOSTNAME=jetstream.atproto.tools 1165 1166# HTTP Caching (Cache-Control headers) 1167CACHE_MAX_AGE=86400 # 24 hours 1168CACHE_STALE_IF_ERROR=172800 # 48 hours 1169CACHE_STALE_WHILE_REVALIDATE=86400 # 24 hours 1170 1171# Logging 1172RUST_LOG=info 1173``` 1174 1175### High-Availability Configuration (Redis) 1176 1177```bash 1178# .env.ha.redis 1179# Required 1180HTTP_EXTERNAL=quickdid.example.com 1181 1182# Network 1183HTTP_PORT=8080 1184DNS_NAMESERVERS=8.8.8.8,8.8.4.4,1.1.1.1,1.0.0.1 1185 1186# Caching (separate Redis instances) 1187REDIS_URL=redis://cache-redis:6379/0 1188CACHE_TTL_MEMORY=300 1189CACHE_TTL_REDIS=3600 1190 1191# Queue (dedicated Redis) 1192QUEUE_ADAPTER=redis 1193QUEUE_REDIS_URL=redis://queue-redis:6379/0 1194QUEUE_REDIS_PREFIX=prod:queue: 1195QUEUE_WORKER_ID=${HOSTNAME:-worker1} 1196QUEUE_REDIS_TIMEOUT=10 1197QUEUE_REDIS_DEDUP_ENABLED=true # Essential for multi-instance 1198QUEUE_REDIS_DEDUP_TTL=120 # Longer TTL for HA 1199 1200# Performance 1201QUEUE_BUFFER_SIZE=10000 1202 1203# Rate Limiting (important for HA deployments) 1204RESOLVER_MAX_CONCURRENT=500 1205RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=10000 # 10 second timeout for HA 1206 1207# Metrics (recommended for HA monitoring) 1208METRICS_ADAPTER=statsd 1209METRICS_STATSD_HOST=statsd:8125 1210METRICS_PREFIX=quickdid.prod 1211METRICS_TAGS=env:prod,service:quickdid,cluster:ha 1212 1213# Proactive Refresh (recommended for HA) 1214PROACTIVE_REFRESH_ENABLED=true 1215PROACTIVE_REFRESH_THRESHOLD=0.7 # More aggressive for HA 1216 1217# Jetstream Consumer (recommended for real-time sync in HA) 1218JETSTREAM_ENABLED=true 1219JETSTREAM_HOSTNAME=jetstream.atproto.tools 1220 1221# Logging 1222RUST_LOG=warn 1223``` 1224 1225### Hybrid Configuration (Redis + SQLite Fallback) 1226 1227```bash 1228# .env.hybrid 1229# Required 1230HTTP_EXTERNAL=quickdid.example.com 1231 1232# Network 1233HTTP_PORT=8080 1234 1235# Caching (Redis primary, SQLite fallback) 1236REDIS_URL=redis://redis:6379/0 1237SQLITE_URL=sqlite:/data/fallback.db 1238CACHE_TTL_MEMORY=600 1239CACHE_TTL_REDIS=86400 1240CACHE_TTL_SQLITE=604800 # 1 week (longer for fallback) 1241 1242# Queue 1243QUEUE_ADAPTER=redis 1244QUEUE_REDIS_TIMEOUT=5 1245 1246# Logging 1247RUST_LOG=info 1248``` 1249 1250### Docker Compose Configuration (Redis) 1251 1252```yaml 1253# docker-compose.redis.yml 1254version: '3.8' 1255 1256services: 1257 quickdid: 1258 image: quickdid:latest 1259 environment: 1260 HTTP_EXTERNAL: quickdid.example.com 1261 HTTP_PORT: 8080 1262 REDIS_URL: redis://redis:6379/0 1263 CACHE_TTL_MEMORY: 600 1264 CACHE_TTL_REDIS: 86400 1265 QUEUE_ADAPTER: redis 1266 QUEUE_REDIS_TIMEOUT: 5 1267 JETSTREAM_ENABLED: true 1268 JETSTREAM_HOSTNAME: jetstream.atproto.tools 1269 RUST_LOG: info 1270 ports: 1271 - "8080:8080" 1272 depends_on: 1273 - redis 1274 1275 redis: 1276 image: redis:7-alpine 1277 command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru 1278``` 1279 1280### Docker Compose Configuration (SQLite) 1281 1282```yaml 1283# docker-compose.sqlite.yml 1284version: '3.8' 1285 1286services: 1287 quickdid: 1288 image: quickdid:latest 1289 environment: 1290 HTTP_EXTERNAL: quickdid.example.com 1291 HTTP_PORT: 8080 1292 SQLITE_URL: sqlite:/data/quickdid.db 1293 CACHE_TTL_MEMORY: 600 1294 CACHE_TTL_SQLITE: 86400 1295 QUEUE_ADAPTER: sqlite 1296 QUEUE_BUFFER_SIZE: 5000 1297 QUEUE_SQLITE_MAX_SIZE: 10000 1298 JETSTREAM_ENABLED: true 1299 JETSTREAM_HOSTNAME: jetstream.atproto.tools 1300 RUST_LOG: info 1301 ports: 1302 - "8080:8080" 1303 volumes: 1304 - quickdid-data:/data 1305 1306volumes: 1307 quickdid-data: 1308 driver: local 1309``` 1310 1311## Validation Rules 1312 1313QuickDID validates configuration at startup. The following rules are enforced: 1314 1315### Required Fields 1316 13171. **HTTP_EXTERNAL**: Must be provided 13182. **HTTP_EXTERNAL**: Must be provided 1319 1320### Value Constraints 1321 13221. **TTL Values** (`CACHE_TTL_MEMORY`, `CACHE_TTL_REDIS`, `CACHE_TTL_SQLITE`): 1323 - Must be positive integers (> 0) 1324 - Recommended minimum: 60 seconds 1325 13262. **Timeout Values** (`QUEUE_REDIS_TIMEOUT`): 1327 - Must be positive integers (> 0) 1328 - Recommended range: 1-60 seconds 1329 13303. **Queue Adapter** (`QUEUE_ADAPTER`): 1331 - Must be one of: `mpsc`, `redis`, `sqlite`, `noop`, `none` 1332 - Case-sensitive 1333 13344. **Rate Limiting** (`RESOLVER_MAX_CONCURRENT`): 1335 - Must be between 0 and 10000 1336 - 0 = disabled (default) 1337 - Values > 10000 will fail validation 1338 13395. **Rate Limiting Timeout** (`RESOLVER_MAX_CONCURRENT_TIMEOUT_MS`): 1340 - Must be between 0 and 60000 (milliseconds) 1341 - 0 = no timeout (default) 1342 - Values > 60000 will fail validation 1343 13446. **Port** (`HTTP_PORT`): 1345 - Must be valid port number (1-65535) 1346 - Ports < 1024 require elevated privileges 1347 1348### Validation Errors 1349 1350If validation fails, QuickDID will exit with one of these error codes: 1351 1352- `error-quickdid-config-1`: Missing required environment variable 1353- `error-quickdid-config-2`: Invalid configuration value 1354- `error-quickdid-config-3`: Invalid TTL value (must be positive) 1355- `error-quickdid-config-4`: Invalid timeout value (must be positive) 1356 1357### Testing Configuration 1358 1359Test your configuration without starting the service: 1360 1361```bash 1362# Validate configuration 1363HTTP_EXTERNAL=test quickdid --help 1364 1365# Test with specific values 1366CACHE_TTL_MEMORY=0 quickdid --help # Will fail validation 1367 1368# Check parsed configuration (with debug logging) 1369RUST_LOG=debug HTTP_EXTERNAL=test quickdid 1370``` 1371 1372## Best Practices 1373 1374### Security 1375 13761. Use environment-specific configuration management 13772. Use TLS for Redis connections in production (`rediss://`) 13783. Never commit sensitive configuration to version control 13795. Implement network segmentation for Redis access 1380 1381### Performance 1382 13831. **With Redis**: Use lower memory cache TTL (300-600s) 13842. **With SQLite**: Use moderate memory cache TTL (600-1800s) 13853. **Without persistent cache**: Use higher memory cache TTL (1800-3600s) 13864. **High traffic**: Increase QUEUE_BUFFER_SIZE (5000-10000) 13875. **Multi-region**: Use region-specific QUEUE_WORKER_ID 1388 1389### Caching and Queue Strategy 1390 13911. **Multi-instance/HA deployments**: Use Redis for distributed caching and queuing 13922. **Single-instance deployments**: Use SQLite for persistent caching and queuing 13933. **Development/testing**: Use memory-only caching with MPSC queuing 13944. **Hybrid setups**: Configure both Redis and SQLite for redundancy 13955. **Real-time sync**: Enable Jetstream consumer for live cache updates 13966. **Queue adapter guidelines**: 1397 - Redis: Best for multi-instance deployments with distributed processing 1398 - SQLite: Best for single-instance deployments needing persistence 1399 - MPSC: Best for single-instance deployments without persistence needs 14007. **Cache TTL guidelines**: 1401 - Redis: Shorter TTLs (1-7 days) for frequently updated handles 1402 - SQLite: Longer TTLs (7-90 days) for stable single-instance caching 1403 - Memory: Short TTLs (5-30 minutes) as fallback 14048. **Jetstream guidelines**: 1405 - Production: Enable for real-time cache synchronization 1406 - High-traffic: Essential for reducing stale data 1407 - Development: Can be disabled for simpler testing 1408 - Monitor WebSocket connection health in production 1409 1410### Monitoring 1411 14121. Set descriptive QUEUE_WORKER_ID for log correlation 14132. Use structured logging with appropriate RUST_LOG levels 14143. Monitor Redis memory usage and adjust TTLs accordingly 14154. Track cache hit rates to optimize TTL values 1416 1417### Deployment 1418 14191. Use `.env` files for local development 14202. Use secrets management for production configurations 14213. Set resource limits in container orchestration 14224. Use health checks to monitor service availability 14235. Implement gradual rollouts with feature flags 14246. **SQLite deployments**: Ensure persistent volume for database file 14257. **Redis deployments**: Configure Redis persistence and backup 14268. **Hybrid deployments**: Test fallback scenarios (Redis unavailable)