KIS Open API Runtime Hardening Playbook (Token, Throttle, WebSocket Discipline)

2026-02-25 · finance

KIS Open API Runtime Hardening Playbook (Token, Throttle, WebSocket Discipline)

Date: 2026-02-25 (KST)

TL;DR

When you move from backtest to live KR execution, most outages are not alpha failures — they are control-plane failures:

This playbook turns official KIS constraints into deployable runtime guardrails for Vellab.


1) Official Constraints Snapshot (as of referenced notices)

1.1 REST / WebSocket base limits

From KIS official notice (2025.08.07 기준):

1.2 Token endpoint constraint

Same official notice also states:

1.3 WebSocket misuse enforcement risk

Official notice (2026-02-24) warns that repeated abnormal connect/disconnect loops can trigger temporary IP/appkey blocking.

Examples explicitly called out by KIS:

  1. connect then immediate close, repeatedly
  2. infinite subscribe/unsubscribe loops without validating data reception

1.4 Token lifecycle notes (FAQ + sample repo)

KIS FAQ post (접근토큰발급관리 샘플코드 안내) includes:

Official sample repo README also mentions a practical reissue guidance line of ~1 per minute.

Practical implication: policy details have changed over time. Treat limits as versioned operational config, not hardcoded constants.


2) Production Policy for Ambiguous/Changing Limits

When official pages, FAQ posts, and sample code differ:

  1. Newest official notice wins
  2. If unresolved, run safe fallback mode (stricter pacing)
  3. Store active limits in external config (limits.kis.json) for hot updates
  4. Include limit_version in every order-path log line for forensic traceability

Suggested config shape:

{
  "asOf": "2026-02-25",
  "rest": { "realRps": 20, "paperRps": 2 },
  "token": { "endpoint": "/oauth2/tokenP", "maxRps": 1, "cooldownMs": 60000 },
  "ws": { "maxSessionsPerAppkey": 1, "maxRealtimeRegs": 41 }
}

3) Limiter Architecture (Do Not Use a Single Global Bucket)

Use independent limiters:

  1. rest_real (20 rps target, reserve headroom)
  2. rest_paper (2 rps hard)
  3. token_issue (serialize + cooldown)
  4. ws_control_ops (subscribe/unsubscribe/connect budgets)

Why separate buckets?

Token refresh spikes should never starve order placement. WebSocket churn should never consume REST capacity.


4) Token Management: Singleflight + Stale-While-Valid

Recommended strategy:

Pseudo-flow:

if token.valid_for > threshold:
  use cached token
else:
  acquire distributed lock
  if another worker already refreshed: use new token
  else issue token with limiter + cooldown

5) WebSocket Discipline: Stateful, Not Impulsive

Implement explicit state machine:

IDLE -> CONNECTING -> AUTHENTICATED -> SUBSCRIBED -> STREAMING -> DEGRADED -> RECONNECT_BACKOFF

Guardrails:

If repeated abnormal loops are detected, trip a local breaker before KIS blocks you.


6) Failure Matrix (Operator-Friendly)

Symptom Likely Cause Immediate Action Long-term Fix
403 in paper env wrong host / wrong method verify host + HTTP method startup self-test for env/method mapping
MAX SUBSCRIBE OVER exceeded 41 realtime regs drop lowest-priority sub dynamic subscription budget manager
sudden missing ticks no subscribe success / invalid symbol revalidate code + ack logs subscription ACK audit + symbol validator
token storms no singleflight freeze refresh fan-out distributed token lock + cooldown
frequent disconnects reconnect loop bug trigger breaker + sleep ws finite-state reconnection policy

7) SLO + Alerting Baseline

Minimum metrics:

Recommended alerts:


8) Rollout Plan for Vellab

  1. Build limiter/token/ws modules in shadow mode (observe only)
  2. Enable hard enforcement in paper
  3. Chaos test: forced disconnect, token expiry bursts, over-subscribe attempts
  4. Promote to real with conservative participation caps
  5. Weekly review of KIS notice board deltas and hot-update runtime limits

9) References


One-line takeaway

Treat KIS connectivity as a risk engine: if token, throttle, and WebSocket hygiene are deterministic, your execution layer becomes boring — and boring is exactly what live trading needs.