KYCIS SDK Docs
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: 15

Monitor 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 identity
  • RuntimePolicy — configuration
  • PassiveTracker — timing signals

Activity references:

  • Weak references where possible
  • AndroidUiBridge holds 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 bytes

Disable if not needed:

// Not currently supported
// Trace propagation always enabled

Profiling

Identify bottlenecks:

  1. Backend latency:

    GET /api/activity → check `trace.duration_ms`
  2. SDK internal:

    AI.setStatusListener { status ->
      Log.d("KYCIS", "Status: ${status.code} - ${status.message}")
    }
  3. 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.sqlite3

Optimize:

  • 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

On this page