Documentation Index
Fetch the complete documentation index at: https://docs.clavion.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Performance profile
ISCL is designed for moderate throughput, low-latency local operations. The typical transaction pipeline takes 1-5 seconds, dominated by RPC calls to the blockchain:| Stage | Typical Latency | Bottleneck |
|---|---|---|
| Policy evaluation | <1ms | CPU (in-memory rules) |
| Transaction build | <1ms | CPU (ABI encoding) |
| Preflight simulation (eth_call) | 50-500ms | RPC network round-trip |
| Gas estimation | 50-200ms | RPC network round-trip |
| Approval (auto mode) | <1ms | — |
| Approval (human) | 1s-300s | Human interaction |
| Signing | <5ms | CPU (ECDSA, keystore decrypt) |
| Broadcast | 50-200ms | RPC network round-trip |
| Audit logging | <1ms | Disk I/O (SQLite WAL) |
RPC calls account for 90%+ of pipeline latency. Optimizing SQLite or in-process code yields marginal gains. Optimizing RPC configuration has the largest impact.
SQLite tuning
WAL mode (default)
ISCL enables WAL (Write-Ahead Logging) by default:Synchronous mode
By default, SQLite usesPRAGMA synchronous = FULL in WAL mode. For slightly faster writes at the cost of durability during power loss:
audit-trace-service.ts:
Database size management
The audit trail grows indefinitely. For long-running deployments: Monitor size:cleanupRateLimitEvents() method removes entries older than the rate limit window (1 hour by default). This runs periodically and prevents the rate_limit_events table from growing unboundedly.
Vacuuming: SQLite does not automatically reclaim disk space from deleted rows. After deleting old rate limit events:
Memory-mapped I/O
For read-heavy workloads (frequent dashboard polling), enable memory-mapped I/O:RPC optimization
Provider selection
RPC latency varies significantly by provider. Measure before choosing:- Local nodes (Geth, Reth) provide the lowest latency (<10ms) but require infrastructure
- Paid providers (Alchemy, Infura, QuickNode) typically offer 20-100ms latency
- Free public endpoints are rate-limited and may add 100-500ms latency
Multi-chain RPC configuration
Configure per-chain RPC URLs for optimal routing:Connection reuse
ISCL uses Node.jsfetch for RPC calls, which benefits from HTTP keep-alive by default. To verify:
Rate limiting with providers
RPC providers enforce rate limits (typically 10-100 requests/second for free tiers). ISCL’s pipeline makes 2-4 RPC calls per transaction:eth_call(simulation)eth_estimateGaseth_getTransactionCount(nonce)eth_sendRawTransaction(broadcast)
Transaction throughput
Rate limit configuration
The default rate limit is 10 transactions per wallet per hour. To adjust:- Higher limits increase gas costs and RPC usage
- Rate limiting is enforced in SQLite, so lookup is O(1) via indexed queries
- The cleanup interval for expired rate limit entries is automatic
Concurrent transactions
ISCL processes transactions sequentially per wallet (to manage nonces correctly). Multiple wallets can operate in parallel since each has its own nonce sequence. For higher throughput:- Use multiple wallet addresses (distribute load)
- Ensure policy allows the needed transaction rate per wallet
Approval bottleneck
Inweb or cli approval mode, human confirmation is the primary throughput bottleneck. Each transaction blocks until the user approves or the TTL expires (300 seconds).
Memory usage
Node.js heap
ISCL Core typically uses 50-150MB of heap memory. Key consumers:| Component | Memory | Notes |
|---|---|---|
| Fastify server | ~30MB | Base server + routes + schema compilation |
| SQLite (better-sqlite3) | ~10-20MB | Database file cache (in-process) |
| Pending approval store | ~1KB per request | In-memory Map, cleaned up on TTL expiry |
| Approval token manager | ~1KB per token | In-memory Map, cleaned up on TTL expiry |
| AJV schema validators | ~5MB | Compiled validators, cached |
--max-old-space-size flag controls the V8 heap limit:
PendingApprovalStore cleanup
The in-memory pending approval store runs a cleanup interval every 30 seconds, removing expired entries (>300s TTL). This prevents memory leaks from unanswered approval requests.ApprovalTokenManager cleanup
Consumed and expired tokens are cleaned up every 60 seconds. Each token is ~200 bytes. Even at high throughput (100 tokens/hour), memory impact is negligible.Docker performance
Container resource limits
For production Docker deployments, set resource limits:Volume performance
The SQLite database should be on a Docker volume (not a bind mount) for best I/O performance:Health check configuration
Configure Docker health checks to avoid unnecessary restarts:Monitoring performance
Key metrics to watch
| Metric | Source | Warning Threshold |
|---|---|---|
| RPC response time | Application logs (pino) | >500ms average |
| Audit write latency | SQLite PRAGMA compile_options | >10ms per insert |
| Memory usage | process.memoryUsage() | >400MB heap |
| Pending approvals | /v1/approvals/pending | >10 stale requests |
| SQLite DB size | File system | >1GB (check for vacuum need) |
pino log level tuning
Reduce log verbosity in production:Debug-level logging includes full request/response bodies and can impact throughput at high volumes.
Summary
| Optimization | Impact | Effort | Recommended For |
|---|---|---|---|
| Use paid RPC provider | High | Low | All production deployments |
| Per-chain RPC URLs | Medium | Low | Multi-chain deployments |
SQLite synchronous = NORMAL | Low | Low | Throughput-sensitive deployments |
SQLite mmap_size | Low | Low | Dashboard-heavy usage |
| Multiple wallet addresses | Medium | Medium | High-throughput use cases |
Raise requireApprovalAbove | High | Low | Reduce human bottleneck |
| Docker volume for SQLite | Medium | Low | Docker deployments on macOS |
Next steps
- Configuration Reference — Environment variables and policy settings
- Production Deployment — Production deployment guidance
- Observability — Logging and monitoring setup