Best Practices
Performance Best Practices
Runtime and network efficiency
Event Frequency
Avoid excessive events:
// Bad: Every keystroke
phoneInput.addTextChangedListener {
AI.reportComponentInput(/* ... */) // Too frequent!
}
// Good: Debounced
debouncer.debounce("phone-input", 300) {
AI.reportComponentInput(/* ... */)
}Recommended debounce:
- Text input: 300-500ms
- Slider changes: 100-200ms
- Switch/toggle: Immediate
Payload Size
Keep payloads lean:
// Good: Essential fields only
AI.trackValidationFailure(
failureReasonCode = "pan_invalid",
componentId = "pan_field"
// Skip optional fields if not needed
)
// Avoid: Duplicate data
AI.reportComponentInput(
componentId = "field",
hint = "value",
properties = mapOf(
"hint" to "value" // Duplicate!
)
)Config Refresh
Use throttled refresh, not polling:
<!-- Default: 60 seconds -->
<integer name="kycis_config_refresh_interval_seconds">60</integer>
<!-- Debug: 15 seconds -->
<integer name="kycis_config_refresh_interval_seconds">15</integer>SDK calls fetchConfigAsync() periodically during active sessions.
Trigger Tuning
Adjust thresholds from backend:
# backend/config/kycis.yaml
thresholds:
min_trigger_interval_seconds: 60
high_time_spent_seconds: 30
idle_seconds_threshold: 15Monitor false positive rate in activity stream.
Network Efficiency
Connection Reuse
SDK uses internal HTTP client with connection pooling.
Batch When Possible
If building custom batching:
// Queue events locally
val eventQueue = mutableListOf<Event>()
// Flush periodically
fun flushEvents() {
eventQueue.forEach { event ->
sendEvent(event)
}
eventQueue.clear()
}Note: Current SDK sends events individually.
Memory Management
SDK holds minimal state:
RuntimeContext— session identityRuntimePolicy— configurationPassiveTracker— timing signals
Activity references:
- Weak references where possible
AndroidUiBridgeholds current Activity
Background Behavior
SDK behavior when app backgrounded:
- Passive evaluation pauses
- Config refresh stops
- Voice session continues (if active)
Resume on foreground:
- Passive evaluation resumes
- Config refresh continues
Tracing Overhead
Trace headers add minimal overhead:
traceparent: ~55 bytes
X-Request-ID: ~20 bytesDisable if not needed:
// Not currently supported
// Trace propagation always enabledProfiling
Identify bottlenecks:
-
Backend latency:
GET /api/activity → check `trace.duration_ms` -
SDK internal:
AI.setStatusListener { status -> Log.d("KYCIS", "Status: ${status.code} - ${status.message}") } -
Network:
- Use Charles/Fiddler proxy
- Check response times
- Verify payload sizes
Database (If Using SQLite)
For durable session store:
SESSION_STORE_BACKEND=sqlite
SESSION_STORE_SQLITE_PATH=/data/kycis/store.sqlite3Optimize:
- Use SSD for SQLite
- Periodic cleanup of old sessions
- WAL mode for better concurrency
CDN/Edge
For production scale:
- Serve static assets via CDN
- Use edge locations for voice signaling
- Consider LiveKit Cloud for global distribution