BullMQ로 알림 시스템 운영하기 5편 - 큐는 순서를 보장하지 않는다, 그룹 발송의 동시성
1만 건이 넘는 같은 분류의 알림톡을 그룹 하나로 묶어 보내는 기능을 붙이자, batch 서버가 청크로 잘라 던진 job들이 비동기로 소비되기 시작했다. 그 위에서 그룹은 하나, 발송은 한 번을 지키는 waiting-children의 자리와, 경합 다섯을 하나씩 막고 불변식으로 검증한 과정을 정리했다.
글 5편

1만 건이 넘는 같은 분류의 알림톡을 그룹 하나로 묶어 보내는 기능을 붙이자, batch 서버가 청크로 잘라 던진 job들이 비동기로 소비되기 시작했다. 그 위에서 그룹은 하나, 발송은 한 번을 지키는 waiting-children의 자리와, 경합 다섯을 하나씩 막고 불변식으로 검증한 과정을 정리했다.

S3에 쌓아둔 발송 이력 JSON은 그대로 질의하기 어렵다. 서버리스 질의, 분석 플랫폼 적재, Parquet 변환, Iceberg 네 안을 상시 인프라·조회 비용의 모양·최신성 기준으로 저울질하고, 매일 새벽 Parquet으로 최신화하는 구조를 고른 이유를 정리한다.

발송 이력을 어디에 저장할지에 대한 고민이다. 관계형 DB, RDB·S3 직렬·SNS fan-out·Firehose를 놓고 따진 트레이드오프를 정리했다.

발송 한도는 5초당 100건이었고 우리 평균은 20 req/s였다. 종이 위에서는 한도 이내인데 429가 산발적으로 터졌다. fixed-window 두 개의 시작 시각이 어긋나 있었던 것이 원인이었고, 여기에 다른 팀과 서드파티 계정을 공유하고 있다는 사실이 겹치면서 발송 경로 자체를 다시 설계하게 됐다.

알림톡, 이메일, 푸시처럼 사용자에게 메시지를 보내는 기능은 어느 서비스에나 있다. 그런데 알림 발송을 단순한 HTTP 호출로 구현하다 보면 금세 한계에 부딪힌다. 이 문제들 각각은 다른 도구로도 풀 수 있다. 발송 모듈을 하나로 모으고, 함수 안에 rate limit을 두고, 스케줄러로 시점 분기를 만들고, 발송…