{"id":"IL-0257","org":"Canva","date":"2024-11-12","docs":[],"title":{"en":"canva.com went down for about 50 minutes when 1.5 million requests per second OOM-killed every API Gateway task","ko":"한꺼번에 몰린 요청에 API Gateway 태스크가 모두 OOM 으로 종료돼 canva.com 이 약 50분 동안 열리지 않았다"},"domain":["networking","aws"],"impact":{"scope":"canva.com was unavailable from 9:08 AM UTC to about 10:00 AM UTC; before that the editor's object panel did not load for many users","users":"unknown","region":"The object panel failure hit many users in Asia, and requests backed up from users in Southeast Asia"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":null,"related":[],"sources":[{"url":"https://www.canva.dev/blog/engineering/canva-incident-report-api-gateway-outage/","kind":"blog","archived":"https://web.archive.org/web/20261015213313/https://www.canva.dev/blog/engineering/canva-incident-report-api-gateway-outage/"}],"summary":{"en":"Canva's editor is a single-page application deployed several times a day; each deployment publishes over 100 new static assets, including JavaScript files, to an AWS S3 bucket. Clients fetch them through Cloudflare's tiered cache, where local data centers ask regional or upper-tier data centers and those ask the S3 origin. The editor's JavaScript then calls the API Gateway, the entry point for all of Canva's API requests, which handles authentication, authorization and rate limiting, is built on Netty and runs as an autoscaled group of tasks on Amazon ECS.\n\nAccording to Cloudflare, a stale rule in its traffic management system was sending user IPv6 traffic over public transit between Ashburn and Singapore instead of over its private backbone, and the rule kept Cloudflare's automation from routing around the packet loss. Cloudflare's cache stream feature (Concurrent Streaming Acceleration) consolidates user requests for the same asset into a single request, so more than 270,000 requests waited on one slow fetch and were released together at 9:07 AM UTC. The resulting 1.5 million requests per second met an API Gateway weakened by a performance regression in Canva's telemetry library: certain metrics were re-registered each time a value was recorded, under a lock in a third-party library, and the lock contention on the event loop threads sharply cut how much one task could handle. A fix for that bug had entered the release process the same day, but its impact had been underestimated and it was not expedited. Off-heap memory growth led the OOM killer to terminate all API Gateway containers, faster than autoscaling could replace them.\n\nAt 9:29 AM UTC Canva added a temporary Cloudflare firewall rule that blocked all traffic at the CDN, so new API Gateway tasks could start without being flooded, and later redirected canva.com to its status page. Once the number of healthy tasks was stable, Canva restored traffic step by step, starting with Australian users under strict rate limits. Cloudflare removed the traffic management rule that had sent requests over the lossy path.","ko":"Canva 편집기는 하루에 여러 번 배포되는 단일 페이지 애플리케이션이다. 배포 때마다 JavaScript 파일을 비롯한 정적 자산 100개 이상이 AWS S3 버킷에 올라가고, 클라이언트는 이 자산을 CDN 인 Cloudflare 의 계층형 캐시로 받는다. 편집기는 자산을 받은 뒤 API Gateway 를 호출해 나머지를 불러온다. API Gateway 는 모든 API 요청의 입구이고 인증, 권한, 속도 제한을 처리한다. API Gateway 는 Netty 로 만들었고, Amazon ECS 에서 자동 확장되는 태스크 묶음으로 돈다.\n\n8:47 AM UTC 에 편집기 새 버전이 배포된 같은 시각, Cloudflare 의 낡은 트래픽 관리 규칙이 사용자 IPv6 트래픽을 사설 백본 대신 애슈번과 싱가포르 사이 공용 전송 경로로 보내고 있었다. 이 규칙 때문에 Cloudflare 의 자동화가 패킷 손실을 피해 돌아가지 못했고, 이 경로의 패킷 손실은 최대 약 66% 였다. 객체 패널을 그리는 JavaScript 파일 하나를 받는 데 20분이 걸렸다. Cloudflare 의 캐시 스트림은 같은 자산을 받으려는 여러 요청을 한 요청으로 묶으므로 270,000건 이상의 요청이 같은 스트림을 기다렸다. 요청이 끝나지 않아 오류가 기록되지 않았고 카나리 시스템도 배포를 멈추지 않았다.\n\n9:07 AM UTC 에 파일 받기가 끝나자 기다리던 기기들이 동시에 객체 패널을 불러 API Gateway 에 평소 최대의 3배인 초당 150만 건이 몰렸다. 앞서 텔레메트리 라이브러리를 바꿀 때 성능 저하가 하나 들어가 있었다. 일부 지표가 값을 기록할 때마다 서드파티 라이브러리의 잠금 안에서 다시 등록되는 문제였다. API Gateway 는 이벤트 루프 스레드에서 막히는 작업을 하면 안 되는 구조라서, 부하가 늘자 이 잠금 경합이 태스크 하나의 최대 처리량을 크게 줄였다. 수정은 이미 릴리스 과정에 들어가 있었지만 영향을 작게 보고 서둘러 배포하지 않았다. 요청이 쌓이고 로드 밸런서가 새 연결을 더 열면서 오프힙 메모리가 늘었고, 처음 2분 안에 Linux Out Of Memory Killer 가 모든 컨테이너를 종료했다.\n\n태스크 수를 손으로 늘려도 새 태스크가 곧바로 종료되자, 팀은 9:29 AM UTC 에 Cloudflare 방화벽 규칙으로 CDN 에서 모든 트래픽을 막았다. 새 태스크가 요청을 받지 않은 상태에서 뜨게 하려는 조치였다. 이어서 canva.com 을 상태 페이지로 돌렸다. 정상 태스크 수가 안정되자 엄격한 속도 제한을 건 오스트레일리아 사용자부터 트래픽을 조금씩 되살렸고, canva.com 은 10:00 AM UTC 무렵 복구됐다. Cloudflare 는 문제의 트래픽 관리 규칙을 지웠다."},"trigger":{"en":"At 8:47 AM UTC a new version of the Canva editor page was deployed, and client devices began fetching its new static assets through Cloudflare while the network path between Cloudflare's Singapore and Ashburn locations was losing packets.","ko":"2024년 11월 12일 8:47 AM UTC 에 Canva 편집기 새 버전이 배포돼 클라이언트들이 새 정적 자산을 받기 시작했다. 같은 시각 Cloudflare 의 싱가포르와 애슈번 사이 경로에서 패킷이 손실돼 JavaScript 파일 하나의 전송이 20분 동안 끝나지 않았다."},"severity":"unknown","symptoms":["service-unavailable","oom-killed","high-latency","packet-loss"],"timeline":{"detected_after":null,"resolved_after":"52m"},"date_kind":"incident","detection":null,"components":["cdn","api-gateway","ecs"],"root_cause":"dependency-failure","remediation":[{"text":{"en":"Added a temporary Cloudflare firewall rule at 9:29 AM UTC that blocked all traffic at the CDN so new API Gateway tasks could start","ko":"임시 Cloudflare 방화벽 규칙을 넣어 CDN 에서 모든 트래픽을 막고, 새 API Gateway 태스크가 요청을 받지 않은 상태에서 뜨게 했다."}},{"text":{"en":"Redirected canva.com to the status page","ko":"canva.com 을 상태 페이지로 돌려 사용자에게 장애 중임을 알렸다."}},{"text":{"en":"Restored traffic gradually, starting with Australian users under strict rate limits","ko":"엄격한 속도 제한을 건 오스트레일리아 사용자부터 시작해 canva.com 트래픽을 조금씩 되살렸다."}}],"action_items":[{"text":{"en":"Write a runbook for rerouting, blocking and progressively restoring traffic","ko":"트래픽을 세밀하게 돌리고 막은 뒤 단계적으로 다시 늘리는 내부 런북을 만든다."}},{"text":{"en":"Show users a more informative error page when canva.com is unavailable","ko":"canva.com 을 쓸 수 없을 때 사용자에게 더 자세한 오류 페이지를 보여 준다."}},{"text":{"en":"Raise the baseline number of API Gateway tasks and the memory of each task","ko":"API Gateway 의 기본 태스크 수와 태스크 하나에 주는 메모리를 늘린다."}},{"text":{"en":"Add load shedding rules to the API Gateway for similar traffic patterns","ko":"비슷한 트래픽 패턴에서 실패할 위험을 줄이는 부하 차단 규칙을 API Gateway 에 더한다."}},{"text":{"en":"Load test the API Gateway regularly","ko":"API Gateway 에 정기 부하 테스트를 들인다."}},{"text":{"en":"Deploy the patch for the thread-locking bug in the telemetry library","ko":"텔레메트리 라이브러리의 스레드 잠금 버그를 고치는 패치를 배포한다."}},{"text":{"en":"Add multithreaded tests for the contended code path to the telemetry library microbenchmark suite","ko":"텔레메트리 라이브러리의 마이크로벤치마크 테스트에 스레드 경합을 일으킨 코드 경로의 멀티스레드 테스트를 더한다."}},{"text":{"en":"Use page load completion events as a second canary indicator for page asset releases","ko":"페이지 자산 카나리 릴리스에서 JavaScript 오류율에 더해 페이지 로드 완료 이벤트를 보조 지표로 본다."}},{"text":{"en":"Experiment with adding another rollout stage to the canary to give more time to detect issues","ko":"카나리에 롤아웃 단계를 하나 더 두어 단계적 배포 중 문제를 찾을 시간을 늘리는 실험을 한다."}},{"text":{"en":"Add timeouts so user requests do not wait excessively long for assets","ko":"사용자 요청이 자산을 너무 오래 기다리지 않도록 자산 받기에 타임아웃을 둔다."}},{"text":{"en":"Work with Cloudflare to understand the system interactions behind the incident","ko":"Cloudflare 와 함께 이번 사고에서 여러 시스템이 어떻게 얽혀 작용했는지 자세히 파악한다."}}],"contributing":["overlapping-failures","monitoring-blind-spot","retry-storm","automation-amplified","known-bug-unpatched"],"recurrence_of":null,"symptoms_text":{"en":"On 12 November 2024, after a new version of Canva's editor was deployed at 8:47 AM UTC, the editor's object panel stayed in a perpetual loading state for many users, particularly in Asia. Then from 9:08 AM UTC to about 10:00 AM UTC canva.com was unavailable and all requests to it failed.\n\nThe object panel was waiting for one JavaScript chunk delivered through Cloudflare. The network path between Cloudflare's Singapore (SIN) and Ashburn (IAD) locations had latency problems: the 90th percentile time-for-first-byte rose by over 1700%, packet loss on the path reached about 66% at peak, and the fetch of that one asset took 20 minutes. Canva's canary system, which normally aborts a deployment when errors rise, recorded no errors because the requests never completed, while more than 270,000 user requests for the file waited on the same Cloudflare cache stream.\n\nAt 9:07 AM UTC the fetch completed and all waiting requests finished at once. The object panel loaded on every waiting device together, sending 1.5 million requests per second to the API Gateway, three times the typical peak. Requests backed up, the load balancers opened new connections to the already overloaded tasks, off-heap memory grew, and the Linux Out Of Memory Killer terminated all running API Gateway containers within the first 2 minutes.\n\nAutoscaling started replacement tasks, but each new task was overwhelmed by the traffic as soon as it was marked healthy and was terminated. Raising the desired task count by hand did not stop the new tasks from being terminated.","ko":"2024년 11월 12일 8:47 AM UTC 에 편집기 새 버전을 배포한 뒤, 아시아의 많은 사용자에게 편집기의 객체 패널이 끝없이 로딩 상태로 남았다. 9:08 AM UTC 부터는 canva.com 자체가 열리지 않았다.\n\n같은 시각 Cloudflare 의 싱가포르 SIN 과 애슈번 IAD 사이 네트워크 경로에 지연이 생겨 첫 바이트까지 걸리는 시간의 90번째 백분위수가 1700% 넘게 늘었다. 객체 패널을 그리는 JavaScript 파일 하나는 받는 데 20분이 걸렸다.\n\n요청이 끝나지 않았기 때문에 오류가 기록되지 않았고, 오류가 늘면 배포를 멈추는 카나리 시스템도 배포를 멈추지 않았다. 이 JavaScript 파일을 기다리는 사용자 요청 270,000건 이상이 같은 캐시 스트림에 묶였고, 그래서 동남아시아 사용자의 요청이 쌓였다.\n\n9:07 AM UTC 에 파일 받기가 끝나자 대기 중이던 요청 270,000건 이상이 한꺼번에 완료됐다. 기다리던 모든 기기가 동시에 객체 패널을 불러 API Gateway 에 초당 150만 건의 요청이 몰렸다. 평소 최대 부하의 3배였다.\n\nAPI Gateway 태스크가 요청을 제때 처리하지 못하자 로드 밸런서가 이미 과부하인 태스크에 새 연결을 더 열어 메모리 압박이 커졌다. 오프힙 메모리가 늘면서 처음 2분 안에 Linux Out Of Memory Killer 가 실행 중인 컨테이너를 모두 종료했다. 자동 확장이 이 속도를 따라가지 못해 canva.com 으로 가는 모든 요청이 실패했다.\n\n자동 확장이 띄운 새 태스크는 정상으로 표시되자마자 몰려드는 트래픽을 감당하지 못하고 곧바로 종료됐다. 원하는 태스크 수를 손으로 크게 늘려 봤지만 태스크가 금방 종료되는 문제는 그대로였다."},"updated_at":"2026-11-14T12:33:50.706556Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0257","org_slug":"canva"}