config.yaml file. Validate it with ./blocklight config check.
Overview
The configuration file is organized into several sections:chains- Blockchain connectionsgo_core- Core engine settingsanalysis- Analysis settings (transaction, contract)alerting- Notification channelsaggregation- Noise reductionstorage- In-memory storage limitslogging- Log configurationmonitoring- Prometheus metrics
Network Configuration
Configure blockchain connections. Each chain needs an RPC URL. WebSocket is optional but recommended for real-time monitoring.API Keys: Use
${API_KEY} placeholders in URLs. Set API keys in .env file (see env.template). This keeps sensitive keys out of config.yaml and allows different keys per environment.Chain Settings
enabled (boolean, required)
- Purpose: Enable or disable monitoring for this chain
- Default:
true - Limits: N/A (boolean)
rpc_url (string, required)
- Purpose: HTTP/HTTPS RPC endpoint for blockchain queries
- Format: Must be a valid URL (http:// or https://)
- Security: HTTPS recommended for production
- Limits: N/A (valid URL required)
- API Keys: Use
${YOUR_PROVIDER_API_KEY}placeholders. Set keys in.envfile. - Works with ANY provider:
- Alchemy:
https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY} - Infura:
https://mainnet.infura.io/v3/${INFURA_API_KEY} - QuickNode:
https://your-endpoint.quiknode.pro/${QUICKNODE_API_KEY}/ - Ankr:
https://rpc.ankr.com/eth/${ANKR_API_KEY} - Chainstack:
https://nd-123-456-789.p2pify.com/${CHAINSTACK_API_KEY} - Your own node:
https://your-node.example.com:8545 - Any other EVM-compatible RPC provider
- Alchemy:
ws_url (string, optional)
- Purpose: WebSocket endpoint for real-time block/transaction streaming
- Format: Must be a valid WebSocket URL (ws:// or wss://)
- Behavior: If empty, falls back to polling mode using
polling_interval - Security: WSS (secure WebSocket) recommended for production
- Limits: N/A (valid WebSocket URL or empty string)
- API Keys: Use
${YOUR_PROVIDER_API_KEY}placeholders (same asrpc_url) - Works with ANY provider:
- Alchemy:
wss://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY} - Infura:
wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY} - QuickNode:
wss://your-endpoint.quiknode.pro/${QUICKNODE_API_KEY}/ - Your own node:
wss://your-node.example.com:8546
- Alchemy:
- Recommendation: Always provide WebSocket URL for real-time monitoring
chain_id (integer, required)
- Purpose: Chain identifier (1 for Ethereum, 137 for Polygon, etc.)
- Limits: N/A (must match actual chain ID)
name (string, optional)
- Purpose: Human-readable chain name for logs and alerts
- Limits: N/A
polling_interval (integer, seconds)
- Purpose: How often to poll for new blocks when WebSocket is unavailable
- Limits: Minimum: 1, Maximum: 60
- Recommendations:
- Ethereum: 12 seconds (12s block time)
- Polygon: 2 seconds (2s block time)
- Fast chains (BSC, Arbitrum): 1-3 seconds
- Slow chains: 12-15 seconds
- Warning: Values > 60 seconds may cause missed blocks
batch_size (integer)
- Purpose: Number of transactions to fetch per batch request
- Limits: Minimum: 10, Maximum: 500
- Recommendations:
- High-volume chains (Polygon, BSC): 50-100
- Standard chains (Ethereum): 100
- Low-volume chains: 50-100
- Impact: Larger batches = fewer RPC calls but more memory usage
Environment Variables: Set
{CHAIN}_NODE_URL and {CHAIN}_WS_URL in .env to override defaults. Example: ETH_NODE_URL, POLYGON_NODE_URL. This allows you to use private API keys without committing them.Core Engine Configuration
The core engine processes transactions and evaluates rules. These settings control performance and resource usage.Service Configuration
host (string)
- Purpose: Service hostname (for Docker deployments)
- Limits: N/A
- Default:
"blocklight-core"
port (integer)
- Purpose: gRPC port for API communication
- Limits: Minimum: 1024, Maximum: 65535
- Default:
50051
Rules Configuration
rules_dir (string, required)
- Purpose: Directory containing default detection rules
- Limits: N/A (must be valid directory path)
- Default:
./rules/default
custom_rules_dir (string, optional)
- Purpose: Directory for custom user-defined rules
- Limits: N/A (must be valid directory path if provided)
- Default:
./rules/custom
schema_path (string, required)
- Purpose: Path to JSON schema for rule validation
- Limits: N/A (must be valid file path)
- Default:
./rules/schema/rule_schema.json
Hot Reload Configuration
hot_reload (boolean)
- Purpose: Automatically reload rules when files change (development)
- Limits: N/A (boolean)
- Default:
true - Production: Set to
falsefor production deployments
reload_interval (integer, seconds)
- Purpose: How often to check for rule file changes
- Limits: Minimum: 1, Maximum: 300
- Default:
5 - Recommendations:
- Development: 3-5 seconds
- Production: 30-60 seconds (if hot_reload enabled)
- Warning: Values < 3 seconds may impact performance
Performance Tuning
workers (integer)
- Purpose: Number of parallel goroutines that evaluate rules simultaneously
- Limits: Minimum: 1, Maximum: 64
- Default:
8 - Recommendations:
- Single chain, low volume: 8-12 workers
- Single chain, high volume (Polygon, BSC): 16-24 workers
- Multiple chains: 12-16 workers per chain
- CPU-constrained: 4-8 workers
- Impact: More workers = faster processing but higher CPU/memory usage
- Formula:
workers = (CPU cores × 2) - 2(general guideline)
batch_size (integer)
- Purpose: Number of transactions processed together before evaluating rules
- Limits: Minimum: 10, Maximum: 500
- Default:
100 - Recommendations:
- Fast chains (Polygon, BSC): 50-100
- Standard chains (Ethereum): 100
- Memory-constrained: 50
- Impact: Larger batches = better throughput but more memory per batch
channel_buffer (integer)
- Purpose: Size of internal event channel buffer (prevents “channel full” warnings)
- Limits: Minimum: 100, Maximum: 50000
- Default:
1000 - Recommendations:
- Single chain, low volume: 1000-2000
- Single chain, high volume (Polygon, BSC): 5000-10000
- Multiple chains: 5000-10000 per chain
- Very high volume: 10000-20000
- Warning: If you see
"Event channel full, dropping event"warnings, increase this value - Memory Impact: Each buffered event uses ~1-2KB memory
- Formula:
channel_buffer = (expected_tx_per_second × processing_time_seconds) × 2
Rule Evaluation Limits
max_condition_depth (integer)
- Purpose: Maximum recursion depth for complex nested conditions (prevents stack overflow)
- Limits: Minimum: 1, Maximum: 50
- Default:
10 - Recommendations:
- Simple rules: 5-10
- Complex rules with nested AND/OR: 10-20
- Very complex rules: 20-30
- Warning: Values > 50 risk stack overflow
timeout_seconds (integer)
- Purpose: Maximum time allowed for a single rule evaluation
- Limits: Minimum: 1, Maximum: 60
- Default:
5 - Recommendations:
- Simple rules: 3-5 seconds
- Complex rules with many conditions: 5-10 seconds
- Rules with complex chained methods: 5-10 seconds
- Impact: Rules exceeding timeout are skipped (logged as warning)
connection_pool_size (integer)
- Purpose: Maximum number of concurrent RPC connections per chain
- Limits: Minimum: 1, Maximum: 100
- Default:
10 - Recommendations:
- Single chain: 10-20 connections
- Multiple chains: 10 connections per chain
- High-volume chains: 20-30 connections
- RPC rate-limited: 5-10 connections
- Impact: More connections = faster parallel requests but higher RPC quota usage
- Note: Each chain has its own connection pool
Analysis Configuration
Analyzers run automatically when RPC client is available. Configure what data to fetch and cache.Transaction Analyzer
Always enabled if RPC client is available. Provides essential transaction fields.fetch_receipt (boolean)
- Purpose: Fetch transaction receipt (required for
tx.status,tx.gas_used,tx.logs_count) - Limits: N/A (boolean)
- Default:
true - Required for:
tx.status,tx.gas_used,tx.logs_count,tx.logs - Cost: Low (1 RPC call per transaction)
decode_input (boolean)
- Purpose: Parse function selector from transaction input data
- Limits: N/A (boolean)
- Default:
true - Required for:
tx.function(function selector) - Cost: Negligible (local parsing)
analyze_gas (boolean)
- Purpose: Perform detailed gas analysis (efficiency, cost calculations)
- Limits: N/A (boolean)
- Default:
false - Cost: Negligible (local calculation)
- Use case: Advanced gas monitoring rules
timeout_seconds (integer)
- Purpose: Maximum time to wait for RPC response
- Limits: Minimum: 1, Maximum: 60
- Default:
5 - Recommendations: 5-10 seconds (RPC calls are usually fast)
cache_ttl_seconds (integer)
- Purpose: How long to cache transaction analysis results
- Limits: Minimum: 60, Maximum: 86400 (1 day)
- Default:
300(5 minutes) - Recommendations:
- High-volume chains: 300-600 seconds (5-10 minutes)
- Standard chains: 300 seconds (5 minutes)
- Impact: Longer TTL = fewer RPC calls but potentially stale data
Contract Analyzer
Always enabled if RPC client is available. Provides contract bytecode and metadata.fetch_bytecode (boolean)
- Purpose: Fetch contract bytecode from blockchain (currently not used in rules)
- Limits: N/A (boolean)
- Default:
true - Cost: Low (1 RPC call per unique contract address)
- Caching: Contracts are immutable, so results are cached aggressively
timeout_seconds (integer)
- Purpose: Maximum time to wait for RPC response
- Limits: Minimum: 1, Maximum: 60
- Default:
5
cache_ttl_seconds (integer)
- Purpose: How long to cache contract bytecode (contracts don’t change)
- Limits: Minimum: 300, Maximum: 604800 (1 week)
- Default:
3600(1 hour) - Recommendations: 3600-86400 seconds (1 hour to 1 day)
- Note: Contracts are immutable, so long cache TTL is safe
Aggregation Configuration
Configure detection aggregation to reduce alert noise by grouping related detections. Blocklight uses an adaptive sliding window approach that emits aggregations as soon as they’re ready, not at fixed intervals.Smart Emission: Aggregations are emitted immediately when:
- The time window elapses AND
min_countis reached - OR 3x
min_countis reached (burst detection)
enabled (boolean)
- Purpose: Enable detection aggregation
- Limits: N/A (boolean)
- Default:
true - Recommendation: Keep enabled to reduce alert noise
window_seconds (integer)
- Purpose: Time window (in seconds) to accumulate detections before aggregating
- How it works: Detections are grouped if they arrive within this window from the first detection. Aggregations are emitted as soon as the window elapses (not at fixed intervals).
- Limits: Minimum: 5, Maximum: 3600 (1 hour)
- Default:
15 - Recommendations:
- High-volume environments: 30-60 seconds
- Standard environments: 15-30 seconds
- Forensics/real-time: 5-15 seconds
- Impact: Longer windows = more noise reduction but slightly delayed notifications. However, burst attacks (3x
min_count) trigger immediate emission regardless of window.
min_count (integer)
- Purpose: Minimum number of detections needed to create an aggregated alert
- Limits: Minimum: 1, Maximum: 100
- Default:
2 - Recommendations:
- High-volume environments: 3-5
- Standard environments: 2-3
- Critical alerts: 1 (always alert)
- Impact: Higher values = fewer false positives but may miss single critical events
- Note: Findings below
min_countare emitted individually ifpreserve_individual: true
preserve_individual (boolean)
- Purpose: Keep individual detections accessible in aggregated finding
- Limits: N/A (boolean)
- Default:
true - Recommendations:
- Forensics/debugging:
true(access individual detections) - Memory-constrained:
false(save memory)
- Forensics/debugging:
- Memory Impact:
trueuses more memory but enables detailed analysis - Important: When
true, findings belowmin_countare still emitted as individual alerts
Storage Configuration
Blocklight keeps recent findings in memory for API queries. For long-term storage, use webhook integration.max_findings (integer)
- Purpose: Maximum number of findings to keep in memory (for API queries)
- Limits: Minimum: 100, Maximum: 100000
- Default:
1000 - Recommendations:
- Development/testing: 1000
- Production with API: 5000-10000
- Memory-constrained: 1000-2000
- Memory Impact: Each finding uses ~2-5KB memory
- Formula:
max_findings × 5KB = approximate memory usage - Note: Old findings are automatically evicted when limit is reached
Long-term Storage: For persistent storage, configure a webhook channel to send findings to your database or SIEM system.
Logging Configuration
Configure log output format and destinations.level (string)
- Purpose: Minimum log level to output
- Options:
DEBUG,INFO,WARNING,ERROR - Default:
INFO - Recommendations:
- Development:
DEBUG(verbose) - Production:
INFO(standard) - High-volume:
WARNING(only warnings/errors)
- Development:
format (string)
- Purpose: Log output format
- Options:
json,text - Default:
json - Recommendations:
- Production/containers:
json(structured, easy to parse) - Development:
text(human-readable)
- Production/containers:
file.enabled (boolean)
- Purpose: Enable file logging
- Default:
false - Production: Set to
truefor log persistence
file.path (string)
- Purpose: Path to log file
- Default:
./logs/threat_detection.log
file.max_size_mb (integer)
- Purpose: Maximum log file size before rotation
- Limits: Minimum: 1, Maximum: 1000
- Default:
10 - Recommendations: 10-100 MB depending on log volume
file.max_backups (integer)
- Purpose: Number of rotated log files to keep
- Limits: Minimum: 1, Maximum: 100
- Default:
5 - Recommendations: 5-10 backups
console.enabled (boolean)
- Purpose: Enable console logging
- Default:
true
console.level (string)
- Purpose: Minimum log level for console output (can differ from file)
- Options:
DEBUG,INFO,WARNING,ERROR - Default:
INFO
Monitoring Configuration
Optional: Prometheus monitoring is optional. Blocklight works perfectly without it. Enable only if you need to monitor Blocklight’s health and performance in production.
enabled (boolean)
- Purpose: Enable monitoring features
- Default:
true
prometheus.enabled (boolean)
- Purpose: Enable Prometheus metrics endpoint (optional)
- Default:
true - Requires: REST API enabled (
api.enabled: true) - Note: Blocklight works perfectly without Prometheus. Enable only for production monitoring.
prometheus.path (string)
- Purpose: HTTP path for metrics endpoint
- Default:
"/api/v1/system/metrics"
health_check.enabled (boolean)
- Purpose: Enable health check endpoint
- Default:
true
health_check.interval (integer, seconds)
- Purpose: How often to perform health checks
- Limits: Minimum: 5, Maximum: 300
- Default:
30 - Recommendations: 30-60 seconds
Alert Configuration
Configure notification channels for alerts.enabled (boolean)
- Purpose: Enable alerting system
- Default:
true
channels[].type (string)
- Purpose: Alert channel type
- Options:
log,file,webhook - Limits: N/A
channels[].enabled (boolean)
- Purpose: Enable this specific channel
- Default:
true
channels[].min_severity (string)
- Purpose: Minimum severity level to send through this channel
- Options:
NOTICE,WARNING,CRITICAL - Default:
NOTICE - Recommendations:
- Log channel:
WARNING(reduce noise) - File channel:
NOTICE(capture all) - Webhook channel:
CRITICAL(only critical alerts)
- Log channel:
channels[].path (string, file channel only)
- Purpose: File path for JSONL output
- Limits: N/A (must be writable path)
channels[].url (string, webhook channel only)
- Purpose: Webhook URL for HTTP POST requests
- Limits: N/A (must be valid HTTPS URL)
- Security: Must use HTTPS (HTTP will generate warning)
Environment Variables
Use environment variables for API keys only. RPC URLs are configured inconfig.yaml using ${API_KEY} placeholders.
API Keys in .env
Create a .env file from env.template:
.env file:
config.yaml, use placeholders:
How It Works
- Set API key in
.env:MY_PROVIDER_API_KEY=abc123... - Use placeholder in
config.yaml:rpc_url: https://your-rpc-endpoint.com/v1/${MY_PROVIDER_API_KEY} - Blocklight automatically replaces
${MY_PROVIDER_API_KEY}with the value from.env
Benefits
- Security: API keys stay out of
config.yaml(which may be committed to git) - Flexibility: Different keys per environment (dev, staging, production)
- Simplicity: URLs configured once in
config.yaml, keys per environment in.env
Advanced: Override Complete URLs (Optional)
For advanced use cases, you can override complete URLs using environment variables:config.yaml if set. Recommended: Use API key placeholders instead.
Blocklight automatically loads variables from .env file or system environment.
Configuration Recommendations by Chain Type
Ethereum Mainnet
Polygon (High Volume)
Multiple Chains
Configuration Validation
Blocklight automatically validates your configuration before starting. This prevents system failures due to invalid settings.Automatic Validation
When you run./blocklight start or start with Docker, Blocklight will:
- Load the configuration file
- Validate all settings against strict limits
- Report errors if any values are outside allowed ranges
- Prevent startup if critical errors are found
Manual Validation
Before deploying to production, always validate your configuration:- Check all configuration values against limits
- Report errors and warnings
- Display a summary of enabled features
- Exit with error code if validation fails
Validation Errors
If validation fails, you’ll see detailed error messages:Validation Warnings
Warnings don’t prevent startup but indicate potential issues:- Security warnings (HTTP instead of HTTPS)
- Performance warnings (suboptimal settings)
- Configuration recommendations
Troubleshooting
”Event channel full, dropping event” Warning
Symptom: Logs show{"level":"warn","message":"Event channel full, dropping event"}
Cause: Transactions arriving faster than processing capacity
Solutions:
- Increase
channel_buffer: Set to 5000-10000 for high-volume chains - Increase
workers: Add more parallel processors (up to 64) - Reduce
batch_size: Process smaller batches more frequently - Check RPC latency: Slow RPC calls can cause backlog
High Memory Usage
Symptom: System consuming excessive memory Solutions:- Reduce
channel_buffer: Lower buffer size (minimum 100) - Reduce
storage.max_findings: Keep fewer findings in memory - Reduce
workers: Fewer parallel processors - Optimize rule conditions: Use simple conditions when possible
Slow Rule Evaluation
Symptom: Rules taking too long to evaluate Solutions:- Increase
timeout_seconds: Allow more time (up to 60s) - Reduce
max_condition_depth: Simplify complex conditions - Enable caching: Ensure analyzers have appropriate
cache_ttl_seconds - Optimize rules: Simplify condition logic
Missed Blocks
Symptom: Not detecting transactions from recent blocks Solutions:- Use WebSocket: Provide
ws_urlfor real-time monitoring - Reduce
polling_interval: Check more frequently (minimum 1s) - Check RPC connection: Ensure RPC endpoint is responsive