← 평가·검증

벤치에서 빨랐던 리랭크 설정을 7일 카나리가 되돌렸다

Hindsight-Crew의 리랭크 배치 300은 복제본 벤치에서 PASS를 받았다가 보류로 고쳐졌고, 운영 7일 카나리에서 cold 초과율과 warm p99에 걸려 롤백됐다. 그 판정은 롤백 규칙을 배포 전에 코드에 묶어 둔 판정기에서 나왔다.

목차
  1. 질문
  2. 판정
  3. 근거
  4. 벤치가 PASS를 거둬들인 경과
  5. 벤치가 운영에 남긴 비용
  6. 롤백 규칙을 코드에 묶었다
  7. 2.16일에 이미 넘었다
  8. 판정 장치의 구멍
  9. 같은 벤치를 통과한 다른 후보
  10. 한계·재검토 트리거

질문

리랭크 배치 크기를 128에서 300으로 올리는 후보가 복제본 벤치에서 PASS를 받았다.
속도 비는 0.9365, 6.4% 감소였다.
이 값은 동결 복제본 위에서 warm 요청을 직렬로 재생한 holdout 1회에서 나왔다.
쿼리 단위 지연의 기하평균 비이며 꼬리 기준을 넣기 전의 옛 채택 기준으로 내린 판정이다.

이 PASS를 들고 운영에 넣으면 되는가?
벤치는 이 PASS를 스스로 거둬들였고 마지막 판정은 운영 카나리가 내렸다.

판정

리랭크 배치 300은 운영 7일 카나리에서 cold 7.5초 초과율과 warm p99가 기준선보다 나빠 롤백했다.
그 판정은 배포 전에 코드 상수와 테스트로 묶고 판정기가 기준선과 대조하게 한 롤백 규칙에서 나왔다.

판정 기록은 다섯 단계를 거쳤다. 벤치가 넷, 운영 카나리가 하나다.

옛 기준 holdout - PASS
같은 데이터를 새 꼬리 기준으로 재판정 - 보류
warm 라운드를 늘린 재판정 - PASS로 기록됐다가 보류로 정정
최종 - 보류, warm 대조 무효에 cold 로컬 측정 불가
운영 카나리 - ROLLBACK, B1 불채택

넷째 단계에서 벤치는 합격도 불합격도 내지 못했다.
그래서 카나리는 사후 감시가 아니라 판정 그 자체가 되었고 롤백 기준을 먼저 정한 뒤에 배포했다.
7일 뒤 판정기는 두 축에서 ROLLBACK을 냈고 설정은 그날 128로 돌아갔다.

근거

주장실측측정 조건
벤치는 처음에 PASS를 냈다속도 비 0.9365 [0.9287, 0.9447], 6.4% 감소. 정확도 68/68 동일holdout 1회, 교차 3단계 x 68쿼리. 동결 복제본 warm 직렬 재생. 쿼리 단위 지연의 기하평균 비(후보/기준), 부트스트랩 95% 신뢰구간. 꼬리 기준 도입 전 옛 채택 기준
꼬리 기준을 넣자 같은 데이터가 보류가 됐다p99 비 0.988 [0.947, 1.015], 허용 폭 1%같은 holdout run 재판정, 재측정 없음
warm 재판정의 후보 수치는 개선이었다속도 비 0.9431 [0.9329, 0.954]. 대조 29쿼리교차 6단계 x 68쿼리, 오염 48/408. 대조의 쿼리 하한 30 미달로 형식상 보류
cold는 로컬에서 재지 못했다깨끗한 쌍 0. 가드 창 21개 중 8개가 프로브 계산 직후cold 재생 2회 조기 중단(9/80, 5/5 제외). 메모리 24GB 호스트
기준선cold recall 127, cold p95 5.548초, 7.5초 초과 1/127. warm p95 5.535초, p99 5.653초배포 직전 14일 운영 로그, 배치 128(요청 3개), 벤치 창 제외
중간 점검에서 이미 기준을 넘었다cold p95 6.87초(+24%), 7.5초 초과 2/37카나리 2.16일 경과, 판정 시점 전
최종 판정은 ROLLBACK이었다7.5초 초과 3/81 대 1/127. warm p99 5.795초 대 5.653초7일 구간 운영 로그, 배치 300 대 기준선. 제외 recall 52
통과한 축도 있었다cold p95 5.7284초(문턱 6.1026초 안). warm p95 5.529초 대 5.535초. 재시도 소진 0같은 판정
warm 중앙값은 오히려 빨라졌다warm p50 4.16575초 대 4.5932초(계산, 약 9.3% 감소)같은 판정
예고한 위험이 관측됐다cold 첫 요청 p50 4.7956초 대 2.3563초같은 판정

cold는 사이드카가 5분 이상 쉬다가 받는 첫 포화 recall이고 warm은 그보다 짧게 쉰 뒤에 받는 recall이다.
p95·p99는 지연 분포의 상위 5%·1% 경계다.
A/A는 같은 설정끼리 비교해서 잰 잡음이고 대조는 그 A/A 측정을 가리킨다.

벤치가 PASS를 거둬들인 경과

옛 기준은 warm p95까지만 봤다.
warm p99는 후보/기준이 +0.8%, A/A가 -0.7%여서 잡음 폭의 경계에 걸쳐 있었다.
채택 기준에 warm p95·p99 비열등을 넣고 같은 데이터를 다시 판정하자, p99 신뢰구간 상한이 허용 폭 1%를 넘었다.

warm 라운드를 늘린 재판정은 처음에 PASS로 커밋됐다.
그 커밋 본문에는 미검증 항목이 스스로 적혀 있었다.
"Not-tested: A/A 대조 게이트가 쿼리 수 하한을 보지 않는 점(29 쿼리) - final-review 대상".
약 3시간 뒤 최종 리뷰가 그 결함을 확정했고 대조 게이트를 고치자 판정은 보류로 바뀌었다.
그 수정 커밋에는 판정기 규칙을 사후에 예외 처리하지 않는다는 결정이 남았다.

cold는 재생을 두 번 시작해서 두 번 다 조기에 멈췄다.
벤치 사이드카의 계산 자체가 스왑 아웃을 일으켰고 그 구간이 다음 프로브의 idle 창 앞부분과 겹치면서 프로브가 제외됐다.
호스트가 조용해도 매 프로브가 다음 프로브를 오염시키는 구조였다.

벤치가 운영에 남긴 비용

warm 재판정 run이 돈 약 3.8시간 동안 운영 사이드카에서 503이 6건 났다.
recall은 재시도로 모두 성공했지만 영향을 받은 운영 recall은 20.6초가 걸렸다. 평소에는 5~8초다.
운영 사이드카가 오래 쉬다가 첫 요청을 받는 순간에 벤치 사이드카도 계산 중이면 대기 시간이 7.5초를 넘었다.
벤치 간섭 가드는 호출과 호출 사이에서만 멈추므로, 이미 진행 중인 호출과의 충돌은 막지 못했다.
그래서 카나리 기간에는 벤치를 돌리지 않는다는 조건이 붙었다.

롤백 규칙을 코드에 묶었다

규칙은 배포 전에 승인을 받아 이슈 댓글로 고정했다.
cold 포화 recall에서 재시도 소진이 1건이라도 나오면 즉시 롤백한다.
판정은 cold recall 20건과 7일 중 늦게 도달하는 쪽에서 내린다.
악화는 다음 셋 중 하나에 해당하는 경우다. 7.5초 초과율이 기준선보다 높으면서 2건 이상인 경우, cold p95가 기준선보다 10% 이상 느린 경우, warm p95·p99가 기준선보다 느린 경우다.

같은 댓글에는 실패의 모양도 미리 적어 두었다.
warm 조건 옆에는 "벤치 기대는 약 5% 빠름 - 느려지면 벤치와 운영이 다르다는 신호"라고 썼고
알고 있는 위험으로는 "첫 요청 계산이 128 보다 길다 - 7.5s 에 가까워지는지가 핵심 관측점"을 올렸다.

판정 도구를 만드는 이슈는 문제를 이렇게 정의했다.
"규칙과 기준선 수치를 배포 전에 코드로 고정하지 않으면 판정 뒤에 규칙을 고칠 여지가 생긴다."
규칙 상수 12개를 판정 도구 맨 위에 두고 테스트로 그 값을 고정했다.
기준선 파일에도 그 규칙을 함께 담았고 판정기는 기준선의 규칙과 코드의 규칙이 다르면 기준선을 무효로 본다.

이 대조는 나중에 장치를 고칠 때도 제약이 됐다.
로그 꼬리 허용 시간을 새 상수로 추가하면서도 규칙 묶음에는 넣지 않았다.
넣으면 키가 늘어나서 운영 중인 기준선이 무효가 되기 때문이다.

판정 도구가 머지되었고 배포 직전에 기준선을 고정했다. 그로부터 52초 뒤에 카나리가 시작됐다.

2.16일에 이미 넘었다

카나리 2.16일째의 중간 수치는 이미 롤백 기준에 걸려 있었다.
cold p95가 6.87초(+24%), 7.5초 초과가 2/37이었고 warm p95·p99도 기준선보다 느렸다.
그날의 기록은 "7일 조건만 남았다"였다.
규칙상 판정 시점 전에는 재시도 소진만이 롤백 사유였고 재시도 소진은 0건이었다.

7일 뒤 판정에서는 가장 크게 튀었던 cold p95가 5.7284초로 문턱 안에 들어왔다.
롤백 사유는 나머지 두 축인 cold 7.5초 초과율과 warm p99였다.
cold 첫 요청 p50은 4.7956초로 기준선 2.3563초의 두 배가 넘었다. 규칙 댓글이 핵심 관측점으로 올려 둔 바로 그 지점이다.

판정을 확인한 날 내가 처음 한 요청은 결과가 왜 이리 야박한지까지 쉽게 설명해 달라는 것이었다.
롤백은 카나리 뒤로 미뤄 둔 이슈들과 한 번에 묶어 처리하기로 했고, 그날 오후 내가 승인한 첫 작업 창에서 14시 12분부터 11분 동안 실행했다.
사후 점검 1차 결과는 9 GREEN / 1 RED였고 일시적인 부하로 판정한 뒤 2차에서 10 GREEN이 됐다.

판정 장치의 구멍

판정기 자체에도 구멍이 있었다.
카나리가 도는 동안 구멍 넷을 찾아 고쳤고 판정이 난 뒤에 둘을 더 찾았다.

시점구멍그대로 뒀으면
진행 중로그 앞부분이 빠져도 7일을 채운 것으로 봄거짓 PASS
진행 중로그 꼬리 손실, 회전 세대 수, 첫 줄 시각 판정거짓 PASS, 같은 INVALID 알림 반복
진행 중깨진 기준선의 형식 오류가 ROLLBACK과 같은 종료 코드로 나감거짓 ROLLBACK
진행 중남은 옛 회전 파일이 앞 커버리지를 거짓 통과시킴거짓 PASS
판정 뒤끝이 잘린 압축 로그 하나가 판정기 전체를 죽임판정 불능
판정 뒤쓰는 중인 압축 로그의 손상을 영구 손상으로 종결거짓 종결

고치는 동안 이슈마다 제약을 걸었다.
"절대 판정 문턱을 바꾸지 않는다 - 카나리 규칙은 사전 고정이다."
"절대 실제 ROLLBACK 판정 경로(exit 1)를 약하게 만들지 않는다."
그래서 수정은 한쪽 방향으로만 기울었다.
로그 커버리지가 부족하면 PASS·HOLD·PENDING은 막고 ROLLBACK은 막지 않는다.
커버리지만 부족한 경우에는 덮인 구간에서 나타난 지표 악화를 그대로 ROLLBACK으로 판정하고 사유에 커버리지 부족을 병기한다.

판정 뒤에 고친 두 건은 판정을 돌린 코드에는 들어 있지 않았다.

같은 벤치를 통과한 다른 후보

같은 하네스에서 채택된 응답 필드 프루닝은 holdout 비용이 -3.82%였고 운영 20쿼리 재확인에서도 -3.82%에 결과 불변 20/20이었다.
이 후보는 토큰 비용 지표라서 요청 모양과 cold 경로를 건드리지 않는다.
사이드카 내부 배치를 줄인 다음 후보(B2)는 holdout 속도 비 0.9335 [0.9278, 0.9395]로 PASS를 받았다. 사이드카로 가는 요청 모양이 그대로여서 cold 판정을 면제받았다.
벤치가 재지 못한 축, 즉 요청 모양이 바뀐 cold 경로를 건드린 후보는 B1뿐이었다.

한계·재검토 트리거

카나리는 1회뿐이고 쌍 비교 대신 운영 로그의 점추정 문턱으로 판정을 갈랐다.
cold 81건 중 초과가 3건이어서 건수가 작다.
원인도 확정하지 않았다. 배치 300에서는 recall 전체가 요청 하나에 걸린 7.5초 데드라인 안에 끝나야 한다는 구조가 가설로 남아 있다(추정).
데드라인을 올리는 안은 대안에서 제외했다. 실패를 지연으로 바꾸는 트레이드오프를 받아들이지 않는다는 이유에서다.

판정 장치에서는 판정 뒤에도 구멍이 둘 나왔고 사흘 이내의 로그 꼬리 손실은 의도한 한계로 남겨 두고 잡지 않는다.
로그 꼬리 허용 시간은 판정에 쓰이는 상수인데 규칙 묶음 밖에 있어서 기준선 대조가 이 값의 변경을 잡지 못한다.

판정 시점의 cold 20건은 앞서 만든 cold 재생 도구가 판정에 요구하던 최소 쌍 수와 같은 수다.
7일은 카나리를 처음 계획에 넣을 때 정한 감시 기간이고, 복제본에서 재현할 수 없는 deep-cold 요청(4시간 넘게 쉰 뒤의 요청)을 운영에서 보려고 둔 기간이다.

2026-10 기준 / 재검토 트리거: 사이드카 데드라인이 요청 단위에서 recall 단위로 바뀌거나, 배치 150 후보가 같은 판정기 규칙으로 운영 카나리를 통과하면 이 판정을 다시 연다.