ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Cloudflare Workers][운영] waitUntil 30초를 넘는 후처리를 Queue와 Tail Worker로 언제 분리하나
    기타개발지식/풀스택개발 2026. 8. 1. 09:15

    IT 리서치 노트

    [Cloudflare Workers][운영] waitUntil 30초를 넘는 후처리를 Queue와 Tail Worker로 언제 분리하나

    Cloudflare Workers에서 waitUntil을 한 번 쓰기 시작하면 뒤로 갈수록 더 많은 후처리를 같은 바구니에 넣기 쉽다. 하지만 2026년 8월 1일 기준 Cloudflare 공식 문서를 다시 보면 invocation end 뒤 waitUntil은 최대 30초까지만 연장되고, 그 안에 끝나지 않을 작업은 Queue로 빼는 편이 맞다. 이 글은 waitUntil 30초를 넘는 후처리를 Queue와 Tail Worker로 언제 분리해야 하는지 정리한 것이다.

    1. 개요

    결론부터 말하면 응답 필수 작업은 await, 짧은 후처리는 waitUntil, 전달 보장과 재시도가 필요한 작업은 Queue, 로그와 예외 전달은 Tail Worker로 분리하는 편이 안전하다. waitUntil은 만능 비동기 통로가 아니다.

    특히 30초 한도는 invocation end 뒤에만 적용되는 연장 구간이므로 총 wall time과 같은 숫자로 읽으면 remediation이 틀어진다. 후처리 누락은 숫자 한도보다 구조 분리 실패에서 더 자주 시작된다.

    2. 어디서 실제로 막히는가

    실무에서 헷갈리는 지점은 세 가지다. 첫째, 모든 후처리를 waitUntil로 보내면 응답 속도와 안전성을 둘 다 잡을 수 있다고 생각한다. 둘째, waitUntil 안에서 Queue send를 하면서 실패해도 로그가 잘 남을 것이라고 본다. 셋째, 로그와 예외 전달까지 business job과 같은 통로로 넣는다.

    Cloudflare limits 문서는 응답 완료나 client disconnect 뒤 outstanding work는 취소될 수 있고 waitUntil은 최대 30초까지만 연장한다고 적는다. context 문서는 30초가 넘으면 미완료 promise가 취소되고, 그 경고가 Workers Logs와 Tail Workers에 남는다고 설명한다. 같은 문서는 작업이 30초 안에 안 끝나면 Queue를 쓰고, 로그나 예외는 Tail Worker를 쓰라고 권한다. 즉 구조를 나누라는 안내가 이미 공식 문서에 들어 있다.

    • 증상: 응답은 성공했는데 후처리 이메일이나 저장 작업이 간헐적으로 빠진다.
    • 실패: waitUntil 하나로 durable job과 logging을 모두 처리하려 한다.
    • 막힘: Queue send 실패와 business job 실패, 예외 로그 누락을 한 증상으로 묶는다.
    • 누락: Tail Worker를 observability 전용 통로로 두지 않는다.

    3. 실무에서 적용하는 순서

    실무 순서는 네 단계가 가장 효율적이다. 먼저 후처리가 응답 필수인지 아닌지를 구분한다. 다음으로 30초 안에 끝날 짧은 작업만 waitUntil로 보낸다. 세 번째로 재시도와 전달 보장이 필요한 작업은 Queue producer/consumer로 분리한다. 마지막으로 로그와 예외는 Tail Worker로 분리해 원 Worker 상태와 독립적으로 수집한다.

    1. 응답 필수 작업은 await로 남긴다.
    2. 짧은 후처리만 waitUntil로 보낸다.
    3. durable handoff가 필요하면 Queue를 쓴다.
    4. 로그와 예외는 Tail Worker로 분리한다.

    실제로는 요청 경로에서 await 대상을 확인하고, waitUntil 작업 목록을 저장하고, Queue send 성공 여부를 로그로 확인하고, consumer 처리 시간을 조회하고, Tail Worker에 예외 이벤트가 도착했는지 다시 확인하는 식으로 운영해야 한다. 메트릭 화면에서는 subrequests, wall time, outcome을 같이 보고, 로그 화면에서는 cancel warning과 exception 필드를 같이 본다. 이 절차를 incident 템플릿에 고정해 두면 숫자 문제와 생존 시간 문제를 더 명확하게 분리할 수 있다.

    incident_note:
    await_fetch_count=2
    wait_until_tasks=1
    queue_send_ok=true
    queue_consumer_ms=4200
    tail_error_events=0
    disconnect_warning=false

    이렇게 나누면 incident를 설명하기 쉬워진다. waitUntil 취소인지, Queue 소비 지연인지, Tail Worker 로그 손실인지가 서로 다른 대책으로 연결되기 때문이다.

    4. 공식 문서와 예시 화면으로 확인하기

    첫 공식 화면은 HTTP-triggered Worker의 실행 수명 설명이다. 여기서 먼저 봐야 할 것은 총 wall time과 invocation end 뒤 남는 작업의 수명이 다른 축이라는 점이다.

    Cloudflare는 HTTP-triggered Worker 총 duration에는 hard limit이 없지만, 응답 뒤 남는 작업은 waitUntil로 최대 30초까지만 연장된다고 설명한다.
    Cloudflare는 HTTP-triggered Worker 총 duration에는 hard limit이 없지만, 응답 뒤 남는 작업은 waitUntil로 최대 30초까지만 연장된다고 설명한다.

    즉 후처리 누락을 timeout 하나로 뭉치면 안 된다. response 동안 살아 있는 작업과 invocation end 뒤 작업을 따로 봐야 한다.

    두 번째 화면은 waitUntil의 정확한 역할을 보여 준다. 반환 응답을 막지 않고도 후처리를 연장할 수 있지만, 그것이 무제한 큐를 뜻하지는 않는다.

    waitUntil은 응답 뒤 작업을 이어 가는 보조 수단이지만, 같은 요청 안에서 공유되는 30초 한도를 가진다.
    waitUntil은 응답 뒤 작업을 이어 가는 보조 수단이지만, 같은 요청 안에서 공유되는 30초 한도를 가진다.

    후처리가 analytics, cache write, fire-and-forget webhook 정도라면 충분할 수 있지만, 재시도와 전달 보장이 필요한 작업이면 다른 도구가 필요하다.

    세 번째 자료는 Queue 문서의 전달 보장 설명이다. waitUntil이 짧은 후처리용이라면 Queue는 재시도와 전달 보장을 위한 통로라는 차이가 여기서 분명해진다.

    Cloudflare Queues 문서는 쓰기가 성공하면 메시지가 유실되지 않도록 설계됐다고 설명한다.
    Cloudflare Queues 문서는 쓰기가 성공하면 메시지가 유실되지 않도록 설계됐다고 설명한다.

    이미 client disconnect와 waitUntil 취소 글이 취소 신호를 다뤘다면, 이번 글은 그 다음 단계인 구조 분리를 정리한 후속편이다.

    결정표를 한 번 만들어 두면 어떤 후처리를 어디로 보내야 할지 팀 합의가 빨라진다. 모든 것을 waitUntil로 보내는 습관을 끊는 데 가장 유용한 표다.

    후처리를 await, waitUntil, Queue, Tail Worker로 나누는 기준표다.
    후처리를 await, waitUntil, Queue, Tail Worker로 나누는 기준표다.

    숫자 한도와 실행 수명 분기는 기존 subrequests 글과 연결해서 보면 더 자연스럽다.

    코드 구조로 보면 더 분명하다. 응답 필수 작업과 후처리, durable handoff, 로그 스트림을 따로 적어 두면 운영 중 왜 누락됐는지 설명이 빨라진다.

    waitUntil, Queue, Tail Worker를 역할별로 분리한 예시다.
    waitUntil, Queue, Tail Worker를 역할별로 분리한 예시다.

    핵심은 후처리의 성격을 먼저 자르는 것이다. 빠른 analytics와 재시도 필요한 job은 같은 칸에 두지 않는 편이 낫다.

    마지막 자료는 운영 체크리스트다. incidents를 기록할 때 subrequests, wall time, waitUntil, queue handoff, tail logs를 한 템플릿에 넣으면 원인 분리가 빨라진다.

    Queue handoff와 Tail Worker 분기까지 포함한 운영 체크리스트다.
    Queue handoff와 Tail Worker 분기까지 포함한 운영 체크리스트다.

    Metrics와 Logs를 같은 incident 메모에 넣는 습관이 중요하다.

    5. 주의사항과 리스크

    첫 번째 리스크는 waitUntil이 있으니 후처리가 충분히 안전하다고 생각하는 것이다. 두 번째는 Queue send를 waitUntil에 올려 두고 send 오류가 암묵적으로 무시될 수 있다는 문구를 놓치는 것이다. 세 번째는 예외 로그 전달까지 same-path business logic에 섞어 두는 것이다.

    운영 전에 확인할 때는 waitUntil task, queue producer, queue consumer, tail handler 네 칸을 같은 incident 템플릿에 넣는 편이 좋다. 그래야 어느 통로가 실패했는지 바로 적을 수 있다.

    • waitUntil은 짧은 후처리용 보조 수단으로만 쓴다.
    • Queue는 전달 보장과 재시도가 필요한 작업에 쓴다.
    • Tail Worker는 로그와 예외 통로로 따로 둔다.

    6. 결론

    Cloudflare Workers 후처리는 waitUntil 하나로 몰아두기보다 역할별로 분리하는 편이 안전하다. 30초 안에 끝나는 짧은 작업만 waitUntil로 두고, durable job은 Queue로, 로그와 예외는 Tail Worker로 보내면 취소와 누락을 훨씬 짧게 설명할 수 있다.

    Queue로 분리한 뒤에는 retry를 몇 번 둘지와 DLQ를 붙일지가 다음 운영 기준이 된다. 이 판단은 retry 3회 기본값과 DLQ 후속 글에서 이어진다.

    • waitUntil은 짧은 후처리만 맡긴다.
    • 30초를 넘는 작업은 Queue로 넘긴다.
    • 로그와 예외는 Tail Worker로 분리한다.

    7. 참고 링크

    1. https://developers.cloudflare.com/workers/platform/limits/
    2. https://developers.cloudflare.com/workers/runtime-apis/context/
    3. https://developers.cloudflare.com/queues/reference/how-queues-works/
    4. https://developers.cloudflare.com/workers/runtime-apis/handlers/tail/
Designed by Tistory.