Incident Library
  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례13건

13건 중 8~12번째

  1. 증상

    2025-09-22 11:05 UTC 에 Railway 프로젝트 캔버스가 열리지 않는다는 첫 신고가 들어왔다. 캔버스는 실제 오류를 보여 주지 않고 끝없이 로딩 상태에 머물렀다.

    촉발

    코드 정리 중 쓰지 않는 컬럼을 지우는 스키마 변경을 했는데, 뒤이은 코드 변경이 그 일부를 의도치 않게 되돌려 프런트엔드가 쓰는 핵심 API 가 실패했다. 이 문제를 고친 뒤 밀린 배포가 한꺼번에 시작되면서, 몇 버전 올라간 PgBouncer 를 쓰던 Control Plane 이 부하를 이기지 못했다.

    원인
    구성 요소
    기여 요인
    감지

    11:05 UTC 에 사용자들이 Railway 프로젝트 캔버스가 열리지 않는다고 신고했다. 두 번째 문제는 11:48 UTC 에 Control Plane 의 자원 사용이 비정상으로 늘고 API 지연이 높아지면서 드러났다.

    조치
    • 사고를 선언하고 15분 안에 수정을 배포해 프로젝트 캔버스 문제를 풀었다.
    • 먼저 Free, Trial, Hobby 등급 사용자의 배포를 멈춰 Pro 사용자는 평소대로 배포하게 하고 배포 대기열이 차츰 줄게 했다.
    • 가장 불안정할 때는 Pro 를 포함한 모든 새 배포를 최대 20분 멈춰 대기열을 더 줄였다.
    • Control Plane 데이터베이스의 CPU 와 메모리를 늘리고, 커넥션 한도를 조정하고, IOPS 용량을 늘렸다.
    • 설정을 손보는 대신 안정적이던 이전 PgBouncer 버전으로 곧바로 롤백했고, 성능이 100배 좋아지며 모든 지표가 정상으로 돌아왔다.
    • 롤백 뒤 Pro 가 아닌 사용자 모두의 배포를 다시 열었다.
    • 21:27 UTC 에 사설 네트워크와 그 엔드포인트가 대시보드에 보이지 않던 드문 경우를 뒤늦게 고쳤다.
    후속 조치
    • Control Plane 저장 계층의 큰 부분을 Postgres 밖으로 옮기는 재설계를 계속한다. 이 작업은 3분기 초에 시작했고, 한 리전의 Control Plane 장애가 플랫폼 전체에 번지는 것을 막고 지금의 Postgres 보다 몇 자릿수 높은 IOPS 를 낼 것을 목표로 한다.
    • CI 파이프라인 검증을 강화해 중단을 일으키는 스키마 변경이 운영에 닿지 못하게 하고, 백엔드 배포 전에 스키마 호환성을 자동으로 검사한다.
    • PgBouncer 노드의 CPU, 메모리, 커넥션 풀 사용률을 모니터링하고 알림을 건다.
    • PgBouncer 업그레이드는 한꺼번에 하지 않고 인스턴스마다 단계적으로 적용한다.
    교훈

    Railway 는 호환되지 않는 스키마 변경이 운영에 닿지 않았다면 이번 연쇄 장애가 없었을 것으로 보았다. PgBouncer 의 성능 저하를 미리 알았다면 훨씬 빨리 복구할 수 있었다고 했다. PgBouncer 를 한꺼번에 올리지 않고 인스턴스마다 차례로 올렸다면 전체에 퍼지기 전에 버전별 성능 문제를 찾았을 것이라고도 했다.

  2. 증상

    2025년 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다. 그 뒤 9월 18일까지 고객 트래픽에서 요청 실패와 지연 급증이 간헐적으로 이어졌다.

    촉발

    2025년 9월 14일 클라우드 사업자가 Clerk 의 Postgres 데이터베이스를 마이너 버전으로 자동 업그레이드했다. 이 업그레이드에는 Postgres 가 연결 잠금을 다루는 방식의 큰 내부 변경이 들어 있었다.

    원인
    구성 요소
    기여 요인
    감지

    9월 14일 업그레이드 직후 내부 모니터링이 데이터베이스 부하 증가를 잡았지만 견딜 만한 수준이었고 지연에는 영향이 없었다. 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다.

    조치
    • 비용이 큰 쿼리 여러 개를 최적화해 데이터베이스의 기본 부하를 영구히 줄였다. 주요 인덱스를 다듬고 전체 재색인을 해 데이터베이스 오버헤드도 줄였다.
    • 안정성을 지키려고 남용 트래픽 차단을 잠시 강화했다. 효과는 있었지만 정상 요청 일부가 HTTP 429 로 거부됐을 수 있다.
    • 9월 17일 07:15 UTC부터 08:10 UTC까지 수동 마이너 버전 업그레이드를 하고 데이터베이스 용량을 늘렸다. 데이터베이스 상태가 눈에 띄게 나아졌고 지연 급증이 다시 사라진 듯했다.
    • 연결 재생성 시각이 서로 맞춰지지 않도록 연결 풀링 전략에 지터를 넣었다. 배포 직후 데이터베이스 부하가 장애 전보다 낮아졌고 지연 급증이 사라졌다.
    후속 조치
    • 업그레이드와 다운그레이드를 더 통제할 수 있고 지금 사업자보다 성능이 나은 데이터베이스 솔루션을 검토한다.
    • 가입과 로그인 인프라를 시스템의 다른 부분에서 떼어 내는 식으로 서비스 격리를 넓힌다.
    • 비용이 큰 쿼리 목록을 계속 따라가며 데이터베이스 성능을 더 끌어올린다.
    • 애플리케이션 하나를 다른 애플리케이션과 격리하는 테넌트 격리 방법을 검토한다. 이 작업은 샤딩과 멀티테넌트 인프라의 최신 방식을 살펴보는 일이라 다른 개선보다 오래 걸릴 가능성이 크다.
    교훈

    Clerk 는 돌아보면 원인이 단순해 보이지만 여러 요인이 겹쳐 찾기 어려웠다고 밝혔다. 첫째, 연결 지표를 60초 간격으로 수집해 15분마다 몇 초 안에 일어나는 재생성 주기가 대시보드에 드문드문한 급증으로만 보였다. 둘째, 같은 시기의 사기 가입 공격이 약 10분 주기로 부하를 만들어 원인을 그쪽으로 의심하게 했다. 셋째, 10분, 15분, 30분 간격의 정기 작업과 예약 쿼리가 급증 시각과 맞아떨어져 조사를 흩뜨렸다. 넷째, 같은 연결 풀링 로직을 쓰는 Backend API 에는 급증이 잘 보이지 않았는데, Clerk 는 Backend API 가 관리하는 연결 수가 훨씬 적어 재생성이 맞춰져도 데이터베이스가 감당했기 때문으로 봤다. 다섯째, 장애 중에 건 배포 동결은 평소 배포가 연결 생성 시각을 흩어 주던 효과를 없애 문제를 키웠다. 이 관계가 직관적이지 않아 연결 동기화를 가리키는 가장 분명한 신호가 가려졌다.

  3. 증상

    2025년 1월 29일 16:05 UTC 에 us-east-1 의 Supavisor 클라이언트 대다수가 연결이 끊겼고 다시 연결하는 데 자꾸 실패했다. Supavisor 는 Postgres 연결을 관리하는 연결 풀러다. Supabase Storage 연결도 함께 문제를 겪었다.

    촉발

    us-east-1 에 Supavisor 2.0 으로 올리는 메이저 업그레이드를 배포한 뒤, :ets.select_delete 작업이 실패해 ETS 테이블이 손상되었다.

    원인
    구성 요소
    기여 요인
    –
    조치
    • 16:11 UTC 에 이전 Supavisor 버전으로 롤백을 시작했고, 16:53 UTC 에 롤백이 끝나 이전 안정 버전으로 정상 동작이 돌아왔다.
    후속 조치
    • 롤백 시간을 40분에서 90초 안으로 줄인다.
    • 클라이언트 연결이 끊기는 것을 2분 안에 잡도록 알림을 고친다.
    교훈

    Supabase 는 이 장애로 롤백이 느리고, 부하가 걸린 상태에서 예상하지 못한 장애를 견디는 힘이 약하다는 점이 드러났다고 밝혔다. 앞으로 비슷한 배포 실패의 영향을 줄이려고 롤백 효율을 높이는 데 집중한다고 썼다.

  4. 증상

    2024-12-13 11:25 AM EST 에 Gadget 은 커넥션 한도를 올리려고 주 Postgres 데이터베이스를 그 자리에서 재시작했는데, 서버가 내려간 뒤 다시 올라오지 않았다. 그동안 Gadget 앱으로 오는 모든 요청이 실패했다.

    촉발

    Gadget 은 플랫폼이 커지며 Postgres 의 max_connections 한도에 닿아 생기던 짧은 장애를 끝내려고, 이 값을 올리는 긴급 설정 변경을 결정했다. max_connections 는 서버를 재시작해야만 바뀌므로 11:25 AM EST 에 데이터베이스를 그 자리에서 재시작했다.

    원인
    구성 요소
    기여 요인
    감지

    Gadget 은 11:25 AM EST 에 재시작한 데이터베이스가 기대대로 다시 올라오지 않는 것을 11:26 AM 에 확인했다.

    조치
    • 데이터베이스 서버를 하드웨어 리셋해 메모리 조각화를 없앴고, 11:50 AM EST 에 데이터베이스가 다시 올라왔다.
    • 데이터베이스가 멈춘 동안 오토스케일러가 줄인 컴퓨트를 당시의 거의 4배로 다시 띄웠고, 이 확장은 성공했지만 서비스 저하가 20분 더 이어졌다.
    후속 조치
    • 이번처럼 중단을 일으키는 데이터베이스 작업은 앞으로 replica 를 만들어 장애 조치하는 방법으로만 한다. 새 replica 를 먼저 띄우면 넘어가기 전에 운영 인프라 안에서 동작을 확인할 수 있다.
    • Black Friday 와 Cyber Monday 전의 용량 계획을 훨씬 공격적으로 세워 부하 6배 증가에 대비하고, 충분한 시간을 두고 종합 부하 시험을 해서 준비가 됐는지 확인한다.
    • 계획된 중단은 상태 페이지와 커뮤니티 Discord 로 미리 알리고, 계획된 점검과 서비스 장애의 차이를 분명히 알리도록 표준 운영 절차를 다듬는다.
    • 계획해 온 데이터베이스 샤딩 프로젝트를 끝내 Gadget 앱마다 다른 데이터베이스를 쓰게 한다. 그러면 데이터베이스 설정 변경에 카나리 배포와 블루/그린 구성을 써서 고객 앱에 닿기 전에 충분히 시험하고, 장애 범위도 좁힐 수 있다.
    • 이미 진행 중인 무중단 데이터베이스 장애 조치 시스템을 완성해 어떤 앱도 멈추지 않고 데이터베이스 크기와 설정을 바꿀 수 있게 한다.
    • 오토스케일러의 최소 규모를 크게 높였다. 앞으로 장애가 나도 컴퓨트가 훨씬 덜 줄어 복구가 빨라진다.
    교훈

    Gadget 은 그 자리에서 재시작하는 방법을 고른 것을 판단 착오로 보았다. 확신할 수 없고 겪어 본 적 없는 상태로 시스템을 몰아넣은 위험한 선택이었다는 것이다. Gadget 은 모든 실패 상태를 미리 알 수는 없어도 처음 보는 실패 상태로 들어가는 일은 대개 피할 수 있다고 했다. Black Friday 와 Cyber Monday 의 용량 계획이 두 배로 잡혀 거의 5배의 부하를 감당하지 못했다. 제대로 계획했다면 점검 시간을 미리 잡고 스테이징에서 연습할 수 있었다. 새 데이터베이스 설정을 사용자에게 영향 없이 운영과 비슷한 환경에서 시험할 방법도 없었다. 통합 테스트는 합성 Postgres 데이터베이스와 쿠버네티스 인프라에서 돌기 때문에, 몇 달 동안의 운영 부하가 만드는 메모리 조각화나 메모리 사용 문제를 재현하지 못한다.

  5. 증상

    2022년 11월 23일 9:39 UTC 에 트래픽 전부가 새 Aurora PostgreSQL 14.x 클러스터로 넘어갔고, 지연이 나빠져 인프라 팀이 조사를 시작했다. 9:54 UTC 에는 쿼리가 평소보다 훨씬 오래 걸리면서 데이터베이스 연결을 모두 차지하고 있었다.

    촉발

    복제를 이용해 Aurora PostgreSQL 10.x 클러스터에서 새 14.x 클러스터로 트래픽을 넘겼다. 그런데 가장 큰 테이블 하나의 vacuum 이 전환 전에 끝나지 않아, 새 클러스터의 가장 큰 테이블들에 ANALYZE 가 돌지 않은 상태였다.

    원인
    구성 요소
    기여 요인
    감지

    9:39 UTC 에 트래픽 전부가 새 클러스터로 넘어갔을 때 지연이 나빠 보였고, 인프라 팀이 바로 조사를 시작했다.

    조치
    • 9:54 UTC 에 쿼리가 데이터베이스 연결을 너무 오래 잡지 않도록 데이터베이스 사용자에 statement timeout 을 걸었다.
    • 9:58 UTC 에 로드 밸런서에서 트래픽의 90% 에 503 을 보내 부하를 덜고 시스템이 회복할 여유를 만들었다.
    • 10:00 UTC 무렵부터 오래 걸리는 쿼리에 EXPLAIN 을 돌려 보고, 해만 끼치고 필요 없는 인덱스를 지우기 시작했다.
    • 트래픽을 100% 로 되돌리는 동안 Apple 웹훅을 잠시 받지 않았다.
    • New Relic 이 느린 쿼리마다 돌리는 EXPLAIN 쿼리를 없애려고 New Relic 을 끈 새 릴리스를 냈다.
    • 12:00 UTC 무렵부터 가장 큰 테이블들에 손으로 ANALYZE 를 돌렸다.
    • 미리 준비해 둔 스크립트로 영향받은 시퀀스 값을 자동으로 올려 기본 키 중복을 풀었다.
    • 전환 몇 분 뒤 통합 이벤트 발송 작업이 이벤트 테이블을 갱신하지 못하는 것을 잡고 발송 작업을 손으로 멈췄다.
    • 발송되었지만 데이터베이스에 기록되지 않은 웹훅을 만일에 대비해 다시 보냈다.
    • 13:33 UTC 에 통합 이벤트 발송, ETL, 웹 서버 밖의 작업을 모두 되살렸다.
    후속 조치
    • 사업에 중요한 시기에는 변경 동결을 두는 것을 검토한다.
    • 백엔드 장애 때 SDK 가 얼마나 믿을 만하게 동작하는지 더 잘 알린다.
    • 개발자 대시보드와 기술 담당자에게 보내는 직접 이메일을 써서 유지보수와 장애를 고객에게 더 잘 알린다.
    • 사전 연습에서 트래픽 일부를 재생해 전환 당일과 더 비슷한 조건을 만든다. 이번 연습은 쓰기 트래픽을 재생하지 않았다.
    • API 를 빠르고 안정적으로 유지하려고 비용이 큰 작업을 최대한 비동기로 옮기는 데 더 투자한다.
    • 테이블 인덱스를 다시 검토한다. 쓰이지 않는 인덱스가 있고, 데이터베이스가 쿼리에 그 인덱스를 고르면 성능이 떨어질 수 있다.
    • 데이터베이스 대시보드에서 엔드포인트와 시스템별 부하를 더 잘 보여 줘 부하가 어디서 오는지 빨리 찾게 한다. 이번에는 Apple 웹훅 부하가 복구를 막는다는 것을 아는 데 너무 오래 걸렸다.
    • 장애 중에 고객 지원과 고객 커뮤니케이션 담당을 불러 소통을 맡긴다.
    교훈

    RevenueCat 은 처음부터 롤백했으면 더 나았다고 돌아봤다. 사전 연습에서는 데이터 일관성과 쿼리 성능만 보고 쓰기 트래픽을 재생하지 않았다. 쓰기는 인덱스가 얽히지 않아 읽기보다 단순하다고 여겼기 때문이다. 복제를 멈추고 평소처럼 쓰기를 해 봤다면 문제를 찾을 수 있었다. 시퀀스 상태가 복제되지 않는다는 한계를 놓치고 상태도 함께 복제된다고 가정했다. 사전 연습 때는 새 클러스터가 오래 떠 있어 vacuum 과 통계가 이미 끝나 있었기 때문에 ANALYZE 가 없는 문제를 보지 못했다. 시기로는 추수감사절과 블랙 프라이데이 전에 끝내려 했지만, 미국 지원팀 일부가 이미 휴가 중인 민감한 때였으므로 그다음 주로 미뤘어야 했다고 밝혔다.

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

이 13건에서 가장 많이 나오는 구성 요소: 데이터베이스 프록시와 커넥션 풀러, 데이터베이스. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별6

설정 변경2건

  1. IL-0574 운영 환경의 DB 접속 경로를 Amazon RDS Proxy로 바꾼 지 몇 분 만에 Aurora MySQL writer CPU가 100%에 이르고 에러가 났다
    Safie2026
  2. IL-0499 세션 서버가 대량으로 내려간 뒤 음성 통화 라우팅 서비스가 과부하로 멈춰 음성·영상 통화가 세 시간 넘게 연결되지 않았다

소프트웨어 결함1건

조직
  1. IL-0313 자체 운영 PgBouncer 로 옮기는 운영 카나리에서 일부 요청이 정확히 300초 멈추고 SQLAlchemy 커넥션 풀이 고갈됐다

업그레이드로 깨진 호환성4건

  1. IL-0304 Intercom US 리전에서 Vitess 의 라우팅 설정 VSchema 가 빈 값으로 덮여 서비스 전체가 71분 동안 멈췄다
  2. IL-0316 밀린 배포가 한꺼번에 몰린 Control Plane 에서 새 버전 PgBouncer 가 CPU 와 메모리를 비정상적으로 많이 써 데이터베이스 연결이 타임아웃됐다
  3. IL-0498 Postgres 데이터베이스 부하가 15분마다 치솟아 나흘 동안 요청 실패와 지연 급증이 간헐적으로 이어졌다
    Clerk2025
  4. IL-0308 RevenueCat 이 Aurora PostgreSQL 10 에서 14 새 클러스터로 넘어간 직후 쿼리가 극도로 느려져 대시보드와 SDK 엔드포인트가 세 시간 넘게 실패했다

배포 결함3건

  1. IL-0369 데이터베이스 마이그레이션이 잠금에 막히는 동안 Railway 백엔드 복제본이 헬스 체크에 실패해 대시보드와 API 가 멈췄다
  2. IL-0315 약 10억 행 테이블에 인덱스를 만드는 스키마 변경이 테이블 전체를 잠가 Railway 의 백엔드 API 가 멈췄다
  3. IL-0307 Supabase us-east-1 에서 Supavisor 2.0 업그레이드 뒤 Postgres 연결 풀러가 테넌트 약 80% 의 연결을 끊었다

클라우드 제공자 장애1건

기여 요인
–
  1. IL-0368 AWS us-east-1 장애 동안 PlanetScale 컨트롤 플레인이 멈추고, 이어 일부 데이터베이스 브랜치가 네트워크 분할로 쿼리에 실패했다

용량 한계2건

  1. IL-0312 max_connections 를 올리려고 재시작한 주 PostgreSQL 데이터베이스가 다시 올라오지 않아 Gadget 의 모든 앱 요청이 멈췄다
    Gadget2024
  2. IL-0302 GitHub 의 공용 MySQL 클러스터 mysql1 이 최대 부하 시간대에 연결이 바닥나 쓰기 작업이 네 번 멈췄다
    GitHub2022