Incident Library

IL-0483 Replicate · 2023-05-11database

PostgreSQL 커넥션이 바닥나 Replicate 웹사이트와 API가 두 시간 가까이 느린 응답과 HTTP 500을 냈다

Replicate 플랫폼의 중심에는 주 데이터 저장소인 PostgreSQL 데이터베이스가 있고, 예측 실행이 이 데이터베이스에 강하게 묶여 있었다. Replicate는 데이터베이스가 잠시 멈춰도 예측이 돌아가도록 캐시와 큐를 더하는 중이었다. 그 일환으로 예측 상태 업데이트를 API 요청 처리기 밖에서 비동기로 데이터베이스에 쓰는 변경을 배포했다. 그리고 5월 10일의 계획된 데이터베이스 유지 보수에 대비해 9일과 10일에 기능 플래그로 넓게 켰다. 10일 14:00 UTC가 조금 지나 프라이머리 크기를 1분 남짓 만에 바꿨고, 이때 대부분의 사용자는 영향을 받지 않았다.

비동기 업데이트는 같은 예측 ID에 INSERT 쿼리를 동시에 보내는 위험한 패턴을 만들었다. 예측 생성 과정에서 약 100~150ms의 지연을 없애자, 그만큼 떨어져 처리되던 업데이트 두 건이 거의 동시에 처리되었다. 고유해야 하는 필드에 같은 값을 넣으려는 쿼리들은 고유 인덱스 잠금을 두고 경합했고, 그동안 모두 느려졌다. 코드는 INSERT가 실패하면 기존 행을 업데이트하도록 되어 있어 바로 문제가 드러나지 않았다. 그러나 시스템은 INSERT가 느려질수록 동시에 도는 쿼리가 늘고 경합도 커지는 불안정한 상태였다.

5월 11일 05:00 UTC가 조금 지나 트래픽 변동으로 이 상태가 무너졌다. INSERT 지연이 수십 초로 뛰었고, 05:45 UTC쯤 커넥션 풀이 가득 차 웹사이트와 API가 느린 응답과 HTTP 500을 냈다. 팀은 전날의 크기 변경을 먼저 의심했고 Crunchy Data와 함께 데이터베이스 문제를 배제했다. 다른 방법을 다 써 본 뒤 07:31 UTC에 기능 플래그로 비동기 예측 업데이트 기능을 모두 껐고, 몇 분 안에 데이터베이스가 회복했다. 장애를 촉발한 그 비동기 코드 덕분에 웹훅을 쓰는 고객은 영향을 덜 받았다.

심각도
–
영향 범위
replicate.com website and API: slow responses and HTTP 500 errors, predictions failing to run; webhook users saw relatively little disruption
영향 사용자
many customers
지역
–
감지까지
1m
복구까지
2h

증상

5월 11일 05:45 UTC쯤 데이터베이스 커넥션 풀이 가득 찼고, 모니터링이 이를 곧바로 감지해 05:46 UTC에 엔지니어를 호출했다. 많은 고객이 replicate.com 웹사이트와 API에서 느린 응답이나 HTTP 500 오류를 받았고, 예측 작업을 제대로 실행하지 못했다.

05:00 UTC가 조금 지나 같은 예측 ID로 들어온 INSERT 쿼리들이 쌓이기 시작했다. 몇 분 사이에 INSERT 지연 시간이 약 1밀리초에서 수십 초로 뛰었다. 동시에 실행되는 쿼리가 늘면서 쿼리마다 커넥션을 하나씩 잡았고, 데이터베이스가 허용하는 최대 커넥션 수를 금세 다 썼다.

커넥션이 남지 않자 새 쿼리는 아예 실행되지 못했다. 웹사이트는 엄밀히는 간헐적으로 실패했지만 이 시간 동안 열리는 때보다 안 열리는 때가 많았다. 예측 결과를 API 폴링 대신 웹훅으로 받는 고객은 영향을 비교적 적게 받았다.

팀은 처음에 전날 데이터베이스 크기를 바꾸면서 무언가를 놓쳤다고 의심했다. 새 프라이머리를 더 느린 디스크로 만들었거나, 새 서버에서 다른 작업이 디스크 I/O를 쓰고 있을 가능성을 살폈다. 비동기 업데이트 코드는 장애 전까지 18시간 넘게 문제없이 켜져 있었기 때문에 원인일 가능성을 낮게 봤다. 데이터베이스 제공사 Crunchy Data가 몇 분 만에 응답했고, 팀과 함께 데이터베이스 쪽 문제를 배제했다.

증상 오류율 상승지연 시간 증가잠금 경합과 교착

원인

촉발
5월 9일과 10일에 기능 플래그로 넓게 켠 비동기 예측 상태 업데이트 기능이 같은 예측 ID로 INSERT 쿼리를 동시에 보내기 시작했다. 5월 11일 05:00 UTC가 조금 지나 평소 수준의 트래픽 변동이 이 불안정한 상태를 무너뜨렸다.

감지

05:45 UTC쯤 데이터베이스 커넥션 풀이 가득 차자 모니터링 시스템이 거의 곧바로 이를 감지해 05:46 UTC에 엔지니어를 호출했다.

조치

후속 조치

교훈

Replicate는 이 장애에 복잡한 시스템 장애의 전형적인 특징이 있다고 보았다. 시스템은 성능이 떨어진 채로도 겉으로는 잘 돌다가 어느 순간 크게 무너졌다. 장애를 촉발한 방어 장치가 같은 장애를 일부 막아 주기도 했다. 변경은 새 위험을 만들지만 위험을 없애는 것도 변경이다. 한 가지를 빠르게 만든 성능 개선이 다른 곳을 훨씬 나쁘게 만들 수 있다.

출처

관련 사례

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 데이터베이스. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.