Incident Library

IL-0510 MIT Open Learning · 2026-03-24databaseaws

MIT Learn 운영 RDS PostgreSQL 의 저장 공간이 임시 파일로 가득 차 learn.mit.edu 가 세 시간 동안 503 과 504 를 냈다

학습 자료 API, 그중에서도 추천 자료 API 가 느렸고, Sentry 는 조회 이벤트를 전부 가져와 건수를 세는 큰 쿼리를 가장 유력한 원인으로 지목했다. 이를 고치려는 쿼리 패턴 변경이 시니어 엔지니어 두 명의 리뷰를 거쳐 정기 릴리스로 배포됐다. 변경은 메인 쿼리 안에 집계를 넣었는데, DRF 가 페이지 응답의 건수를 구하려고 그 쿼리 전체를 COUNT 로 감쌌다. 로컬과 RC 환경처럼 데이터가 작은 곳에서는 문제가 없었지만, 운영에서는 Postgres 서버의 임시 파일이 저장 공간을 모두 채웠다. 18:35 UTC 에 시작된 이 상태에서 WAL 과 체크포인트가 밀리며 새 트랜잭션을 처리하지 못했고, learn.mit.edu 는 503 과 504 를 냈다.

팀은 Qdrant, pgdump 스냅샷 순으로 의심하다가 릴리스의 쿼리 변경을 원인으로 확인하고 롤백했다. 데이터베이스가 안정됐다고 본 뒤에도 503 이 다시 났다. 읽기 복제본 삭제, 복제 슬롯 삭제, VACUUM ANALYZE 를 차례로 했지만 DiskQueueDepth 는 계속 올랐다. AWS 지원과 연결된 상태에서 백업이 끝났고, 엔지니어가 10분 넘게 돌던 쿼리를 pg_terminate_backend 로 종료하자 디스크 큐 깊이와 남은 저장 공간이 정상으로 돌아왔다. 장애는 모두 3시간 35초 동안 이어졌다.

그 뒤 팀은 조회 수를 미리 계산해 둔 열에서 읽도록 고쳐 배포했고, 영향을 받던 API 의 운영 응답 시간이 약 13~15초에서 150~200ms 로 줄었다.

심각도
–
영향 범위
learn.mit.edu returned 503 and 504 errors while the production database was out of storage
영향 사용자
–
지역
us-east-1
감지까지
–
복구까지
3h

증상

learn.mit.edu 가 멈췄다는 보고가 Sentry 이슈 링크와 함께 올라왔다. MIT Learn 의 운영 데이터베이스인 RDS PostgreSQL 인스턴스가 쓸 수 있는 저장 공간을 모두 써 버린 상태였고, 사이트는 503 과 504 오류를 냈다.

엔지니어 한 명이 FreeStorageSpace 지표를 공유했고, 저장 공간을 먹기 시작한 시점은 18:35 UTC 였다. 문제의 중심은 Postgres 데이터베이스 서버가 임시 파일 시스템에 쓰기와 읽기를 끝없이 되풀이한 것이었다. Sentry 에는 504 가 많이 쌓였다.

데이터베이스가 올라와 안정됐다고 선언한 지 20분 뒤에 learn.mit.edu 에서 다시 503 이 났다. 그 뒤 CheckpointLag 지표가 위험해 보였고, 사이트가 돌아왔다는 첫 보고가 나온 뒤에도 RDS 상태를 보는 핵심 지표인 DiskQueueDepth 는 계속 나빴다.

처음에는 Qdrant 클러스터를 의심했지만 곧 운영 데이터베이스 문제로 확인했다. 다음에는 한 엔지니어가 직전에 만든 pgdump 스냅샷을 의심했다가 원인이 아니라고 판단했다. 이어서 방금 배포한 릴리스에 들어간 쿼리 패턴 변경이 의심을 받았고, 변경을 쓴 엔지니어가 원인으로 확인해 롤백했다.

롤백 뒤에도 바로 낫지 않아 여러 조치를 해 봤다. 버퍼에 쌓인 WAL 파일을 비울 여유를 주려고 읽기 복제본을 지웠고, 정리를 빠르게 하려고 복제 슬롯을 지웠지만 효과는 거의 없었다. VACUUM ANALYZE 로 공간을 되찾으려 했으나 DiskQueueDepth 는 계속 올랐고, 이 명령이 쿼리를 더 일으켜 오히려 문제를 키웠을 수 있다.

증상 서비스 중단노드 디스크 가득 참데이터베이스 과부하잠금 경합과 교착

원인

촉발
정기 릴리스 절차로 배포한 변경이 페이지 응답의 메인 쿼리 안에 집계를 넣었다. DRF 는 페이지 응답의 count 칸을 SELECT COUNT * ($QUERY) 로 계산하므로, 운영의 데이터 규모에서 이 쿼리가 임시 파일을 대량으로 만들었다.

감지

엔지니어가 장애를 보고하며 Sentry 이슈를 연결했다. 이어 다른 엔지니어가 운영 데이터베이스의 저장 공간이 바닥난 것을 확인했고, FreeStorageSpace 지표와 Sentry 에 쌓인 504 도 같은 상황을 보여 줬다.

조치

후속 조치

교훈

이 변경은 가장 시니어인 엔지니어 두 명이 꼼꼼히 리뷰했지만 로컬과 RC 환경에서는 아무 문제도 드러나지 않았다. 운영의 데이터 규모와 시스템 부하가 크게 달랐고, 효율적이라고 여긴 COUNT 집계가 디스크 사용량을 폭증시킬 것이라는 점은 당시 시스템 상태만 보고는 알기 어려웠다. 그래서 운영과 같은 규모의 데이터로 부하를 시험할 환경이 필요하다고 팀은 결론지었다.

AWS 지원은 ORM 쿼리 변경을 운영 수준의 데이터를 담은 스테이징에서 시험하고, EXPLAIN ANALYZE 로 실행 계획과 예상 자원 사용을 보며, 시험 중 log_temp_files 로 임시 파일 생성을 지켜보라고 권했다. 폭주하는 쿼리를 막도록 temp_file_limit 를 설정하고, 실행 계획에 따라 work_mem 이나 shared_buffers 를 조정하되 메모리를 너무 쓰면 out of memory 로 장애 조치가 일어날 수 있다는 점도 짚었다. 임시 파일을 많이 쓰는 작업에는 임시 파일을 EBS 대신 로컬 NVMe 에 두는 RDS Optimized Reads 를 고려하라고 했다.

출처

참고 문서

관련 사례

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

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

AI 도구와 스크립트용

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