--- title: Runbook — STUDIO_UNAVAILABLE (Tech Log Studio 일시 장애) category: TRANSIENT_DEPENDENCY error_codes: [STUDIO_UNAVAILABLE] severity: P1 owner: oncall last_updated: 2026-08-18 status: active --- # Runbook: STUDIO_UNAVAILABLE (`runbook://studio/unavailable`) ## 1. Trigger 이 runbook은 Tech Log Studio API(`studio-v1.yaml`)가 `error.code=STUDIO_UNAVAILABLE` (HTTP 503, category `TRANSIENT_DEPENDENCY`, `retryable=true`)을 응답할 때 발동됩니다. - alert name: `studio_error_rate_critical` 또는 `studio_dependency_unavailable` - alert payload 필수 field: `operation`(문서/미리보기/게시 중 어느 슬라이스인지), `error.code`, `error.category`, `dependency_name`(가능하면), `runbook_link` - 임계: - P1: `STUDIO_UNAVAILABLE` 비율이 1분간 Studio 전체 트래픽의 10% 초과 - P2: 단발성 spike이나 5분 내 자연 회복 `StudioExceptionHandler`(adapter/inbound/web)가 `StudioException`을 봉투로 변환하는 지점이므로, 이 코드는 항상 Studio facade/use case(`application-core`)가 자신의 하위 의존성(영속성, 캐시, 오브젝트 스토리지, 렌더링/미리보기 파이프라인 등) 실패를 클라이언트에 안전한 단일 코드로 접어(classify) 던진 결과입니다 — 원인 그 자체가 아니라 **Studio가 판단한 결과**라는 점을 유의합니다. ## 2. First Response (5분 이내) ### Step 1 — 확인 1. 최근 배포 이력 확인 (`app-bootstrap` 롤아웃, config 변경) — 배포 직후 spike면 롤백 우선 검토 2. 로그에서 `StudioException`이 감싸고 있던 실제 원인을 확인: `dev.caskeleton.application.techlog` 패키지의 use case/facade 로그에서 `STUDIO_UNAVAILABLE`로 분류되기 직전의 원인 예외 (`PersistenceFailureException`, `DependencyFailureException` 등)를 추적 3. runtime-health Dependency Matrix에서 Studio가 의존하는 구성요소(DB, 캐시, object storage)의 required/optional 분류와 현재 상태 확인 4. 특정 slice(문서 편집/미리보기/게시)에 국한된 장애인지, Studio 전역 장애인지 구분 ### Step 2 — 임시 격리 - 원인이 특정 하위 의존성이면 해당 의존성의 runbook으로 전환 (예: `runbook://db/unavailable`, `runbook://cache/unavailable`) — `STUDIO_UNAVAILABLE`은 진입점일 뿐, 근본 원인 대응은 하위 의존성 runbook이 담당 - 클라이언트(Frontend)는 이미 `retryable=true`를 신뢰해 지수 백오프 재시도를 수행하므로, 단기 spike는 자연 회복을 우선 관찰 (조기 개입으로 인한 추가 부하 유발 방지) ## 3. Diagnosis - log query: `{service="app"} | error.code="STUDIO_UNAVAILABLE" | stats count by operation` - 원인 추적: 같은 요청의 correlation id로 use case 로그를 따라가 어떤 하위 호출이 `StudioException.withDetails(StudioError.STUDIO_UNAVAILABLE, ...)`로 재분류됐는지 확인 - metric panel: - `http_server_requests_seconds_count{uri=~"/api/v1/studio/.*", outcome="SERVER_ERROR"}` - 하위 의존성 metric (`hikaricp_connections_active`, `resilience4j_circuitbreaker_state`, object storage client 오류율) - 가능한 원인: - DB/캐시/오브젝트 스토리지 등 필수 의존성 장애가 Studio 계층까지 전파 - Studio 자체 리소스 고갈 (스레드풀, 커넥션풀) - 미리보기/렌더링 파이프라인의 타임아웃 누적 - 배포 직후 신규 코드 경로의 미검증 예외가 fallback으로 `STUDIO_UNAVAILABLE`에 접힘 ## 4. Mitigation - 단기: 근본 원인이 확인된 하위 의존성이면 해당 dependency runbook의 mitigation을 적용 - Studio 자체 리소스 고갈이면 인스턴스 스케일아웃 또는 커넥션/스레드풀 상향 검토 - 특정 slice(예: 미리보기)만 영향받는다면 해당 slice만 일시적으로 기능 차단하고 나머지(문서 편집/게시)는 정상 유지 검토 — 전면 장애보다 부분 degrade 우선 - 장기: 반복되는 하위 의존성 장애가 `STUDIO_UNAVAILABLE`로 잦게 나타나면, 해당 의존성의 circuit breaker/timeout 임계를 재조정하고 fallback 경로 보강 ## 5. Escalation - P1 5분 내 회복 신호 없으면 해당 하위 의존성 오너 팀에 page - 여러 slice(문서/미리보기/게시)에서 동시에 발생하면 incident commander 호출 (공유 인프라 계층 문제 의심) ## 6. Recovery / Verification - 회복 확인 metric: `STUDIO_UNAVAILABLE` 비율이 5분간 1% 미만으로 유지 - 하위 의존성 metric(circuit breaker CLOSED, connection pool 정상)도 함께 확인 - post-incident: - 어떤 하위 의존성이 `STUDIO_UNAVAILABLE`로 접혔는지 기록하고 근본 원인 runbook에 링크 - Studio 클라이언트(Frontend `STUDIO_ERROR_CODES`) 쪽 재시도/백오프 동작이 기대대로 작동했는지 확인 - 특정 slice 반복 장애면 chaos test 시나리오 추가 검토 ## 7. Related - error-codes.yaml row: `STUDIO_UNAVAILABLE` (feature-techlog-studio-backend, `dev.caskeleton.application.techlog.error.StudioError.STUDIO_UNAVAILABLE`) - 매핑 지점: `dev.caskeleton.adapter.inbound.web.techlog.StudioExceptionHandler` - 관련 runbook: `runbook://db/unavailable`, `runbook://cache/unavailable` - 관련 branch: [[feature-techlog-studio-backend]]