ES /docs

AWS SQS TLS handshake failure — transient network degradation

RCA: AwsQueueManager::deleteMessage | end - socket hang up

Overview#

What Happened#

2026-07-18 18:15:59 KST 에 cupixworks-capture-postprocessor-agent 가 ap-southeast-2 리전 SQS 큐로 DeleteMessage 호출을 시도하다 AWS SDK 의 재시도 예산을 소진한 뒤 socket hang up 으로 최종 실패했다. 동일 시간대에 ap-southeast-2 SQS 엔드포인트 IP 로 향하는 ECONNRESET 이 반복적으로 관측되었고, 다음 메시지 사이클(약 13초 뒤)부터는 정상 회복되어 단발성 리전 네트워크 flap 로 판단된다. 영향은 SQS 메시지 1건 삭제 실패로, ApproximateReceiveCount 재수신을 통해 재시도되거나 MaxReceiveCount 도달 시 DLQ 로 이동한다.

Quick Facts#

Field Value
exception.class socket hang up (Node.js http agent — AWS SDK v2 wrapped)
exception.message `AwsQueueManager::deleteMessage
top_frame packages/base/src/manager/aws-queue.manager.ts:99
runtime Node.js / aws-sdk v2 (AWS.SQS, apiVersion 2012-11-05)
env production, ap-southeast-2

Affected Teams#

Team / Domain Error Count Impact
scs-assetfuture / cupixworks-capture-postprocessor-agent 1 SQS delete 실패 1건. 메시지가 visibility timeout 후 재수신되어 postprocessing 이 중복 실행될 위험 (idempotency 로 완화)

Timeline#

  1. 2026-07-18 18:14:33 KST — warn connect ECONNRESET 3.27.177.65:443 (ap-southeast-2 SQS 엔드포인트) 및 BaseService::agentScaleOut | undefined queueAttributes (SQS getQueueAttributes 실패)
  2. 2026-07-18 18:14:45 KST — warn connect ECONNRESET 3.27.179.174:443 (다른 SQS 엔드포인트 IP)
  3. 2026-07-18 18:14:47 KST — warn undefined queueAttributes 재발
  4. 2026-07-18 18:15:24 KST — warn socket hang up + undefined queueAttributes (SDK 내부 재시도 로그 누출)
  5. 2026-07-18 18:15:59 KST — error AwsQueueManager::deleteMessage | end - socket hang up (SDK 재시도 5회 소진 후 최종 실패, 콜백 rejection)
  6. 2026-07-18 18:16:12 KST — info AwsQueueManager::deleteMessage | begin/end 정상 성공 (ap-southeast-2, message id 7b1516a6-...) → 네트워크 이슈 자체 회복
  7. 2026-07-18 18:19:19 KST — error BaseService::handlingMessageErrors | ... "error":"undefined response" (관련 후속 처리, 별도 메시지 5aa3710d-...)

Error Log#

Datadog Logs

text
AwsQueueManager::deleteMessage | end - socket hang up

Impact#

  • Service: cupixworks-capture-postprocessor-agent
  • Team: scs-assetfuture
  • 발생 횟수: 1
  • 최초 발생: 2026-07-18 18:15:59 KST
  • 최근 발생: 2026-07-18 18:15:59 KST

Root Cause Summary#

ap-southeast-2 리전의 AWS SQS 엔드포인트 (sqs.ap-southeast-2.amazonaws.com, IP 3.27.177.65, 3.27.179.174) 로 향하는 TCP 연결이 약 1분 30초 동안 ECONNRESET / socket hang up 로 반복 실패했다. AwsQueueManager::deleteMessage 는 aws-sdk v2 의 내장 재시도(MaxRetries=5, RetryInterval=10000ms 기반 지수 backoff) 에 의존하는데, 이 시간 창 동안 재시도 예산이 모두 소진되어 SDK 콜백이 최종적으로 err.message === 'socket hang up' 로 실패했다. 동일 리전 SQS 호출이 이벤트 직후(18:16:12) 정상 회복된 점, 그리고 최근 14일 동안 동일 서비스에서 같은 메시지가 단 1건만 발생한 점으로 볼 때 코드 결함이 아닌 리전 네트워크 flap 이 root cause 다.

Technical Analysis#

Code Path#

  • Entry point: packages/base/src/base-service.ts:224 (deleteByMessage@trace('delete-message') 로 감싸진 얇은 wrapper)
  • 실제 호출: packages/base/src/manager/aws-queue.manager.ts:77 (deleteMessage — Promise 로 감싼 sqs.deleteMessage 콜백)
  • Failure point: packages/base/src/manager/aws-queue.manager.ts:99 — 콜백이 err.message = 'socket hang up' 을 받고 reject(err)
  • 상위 catch: packages/base/src/base-service.ts:107-111 (checkingQueuetry/catchhandlingMessageErrors)
packages/base/src/manager/aws-queue.manager.ts:77-106typescript
deleteMessage = (message: AWS.SQS.Message): Promise<void> => new Promise((resolve, reject) => {
    if (this.debugMode) return resolve();

    const queueUrl = this.queueUrl;
    logger.info('AwsQueueManager::deleteMessage | begin - queue url: %s', queueUrl);
    if (queueUrl == undefined) {
        logger.error('AwsQueueManager::deleteMessage | end - undefined queueUrl');
        return reject();
    }

    const messageReceiptHandle = message && message.ReceiptHandle;
    if (messageReceiptHandle == undefined) {
        logger.error('AwsQueueManager::deleteMessage | end - undefined messageReceiptHandle');
        return reject();
    }

    const params: AWS.SQS.DeleteMessageRequest = {
        QueueUrl: queueUrl,
        ReceiptHandle: messageReceiptHandle
    };
    this.sqs.deleteMessage(params, (err: AWS.AWSError) => {
        if (err) {
            logger.error('AwsQueueManager::deleteMessage | end - %s', err.message);
            reject(err);
        } else {
            logger.info('AwsQueueManager::deleteMessage | end - message id: %s', message.MessageId);
            resolve();
        }
    });
});

SDK 재시도 설정:

packages/base/src/manager/aws-queue.manager.ts:17-21typescript
this._sqs = new AWS.SQS({
    apiVersion: '2012-11-05',
    maxRetries: Constants.MaxRetries,
    retryDelayOptions: {base: Constants.RetryInterval}
});
packages/shared-config/src/constants.ts:8-9typescript
export const MaxRetries = 5;
export const RetryInterval = 10000; // ms

기대 동작: 일시적 네트워크 오류는 aws-sdk v2 가 자체 재시도(최대 5회, base 10초 지수 backoff)로 흡수해야 한다. 5회 재시도 후에도 회복되지 못하면 caller 가 실패를 인지한다.

실제 동작: ECONNRESET/socket hang up 이 최소 18:14:33 ~ 18:15:59 (약 86초) 동안 지속되어 SDK 재시도 예산을 초과했다. 콜백은 err.message = 'socket hang up' 으로 최종 실패했고, AwsQueueManager::deleteMessage | end - socket hang up 이 error 로 기록되었다. 12초 뒤(18:16:12) 동일 큐 URL 로 delete 가 정상 성공한 것으로 보아 원인은 서비스 코드가 아닌 리전 네트워크 flap 이다.

Log Evidence#

Datadog query 1 (클러스터 원본):

text
service:cupixworks-capture-postprocessor-agent status:error @environment:production "AwsQueueManager::deleteMessage"

Datadog query 2 (주변 컨텍스트, 4분 창):

text
service:cupixworks-capture-postprocessor-agent @environment:production
from: 2026-07-18T09:14:00Z, to: 2026-07-18T09:18:00Z

핵심 로그 (KST):

text
2026-07-18 18:14:33 warn  connect ECONNRESET 3.27.177.65:443
2026-07-18 18:14:33 warn  BaseService::agentScaleOut | undefined queueAttributes
2026-07-18 18:14:45 warn  connect ECONNRESET 3.27.179.174:443
2026-07-18 18:14:47 warn  BaseService::agentScaleOut | undefined queueAttributes
2026-07-18 18:15:24 warn  socket hang up
2026-07-18 18:15:24 warn  BaseService::agentScaleOut | undefined queueAttributes
2026-07-18 18:15:59 error AwsQueueManager::deleteMessage | end - socket hang up
2026-07-18 18:16:12 info  AwsQueueManager::deleteMessage | begin - queue url: https://sqs.ap-southeast-2.amazonaws.com/002596530511/cupix-capture-postprocessor-agent-production
2026-07-18 18:16:12 info  AwsQueueManager::deleteMessage | end - message id: 7b1516a6-fe2b-4bc3-ad77-06a3c82ecdaf
  • IP 3.27.177.65, 3.27.179.174sqs.ap-southeast-2.amazonaws.com 의 AWS 소유 대역이다.
  • 클러스터 frontmatter regions: [ap-southeast-2] 와 일치. 다른 리전(us-west-2) 트래픽은 같은 시간대 정상.
  • 14일 창에서 이 에러 문자열은 총 1건만 발생 (service:cupixworks-capture-postprocessor-agent status:error "socket hang up" 쿼리 결과).

관련 이전 인시던트 (status board):

  • 2026-07-13-svc-cupixworks-capture-postprocessor-agent--unknown-1 — 2026-07-13 18:53 ~ 18:57 UTC, 같은 서비스에서 짧게 회복된 degradation 발생 (별도 클러스터 2건). 이번 건과 동일한 flap 계열일 가능성 있으나 별도 지표로 상관관계 확정은 불가 — needs verification.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 ap-southeast-2 리전 AWS SQS 네트워크 flap 으로 인한 일시적 연결 실패, SDK 재시도 예산 초과 ECONNRESET 3.27.177.65:443 / 3.27.179.174:443 (SQS 리전 IP) 18:14:33~18:14:45, socket hang up 18:15:24 warn, 18:15:59 error, 12초 뒤 동일 큐 delete 정상 성공, 14일 창 유일 발생, regions: [ap-southeast-2] Confirmed
H2 queueUrl 또는 ReceiptHandle 이 undefined 로 넘어와 조기 reject aws-queue.manager.ts:82-91 에서 그 경로는 각각 undefined queueUrl / undefined messageReceiptHandle 로그를 남김. 실제 로그는 socket hang up (SDK 콜백 err.message) 이라 다름 로그 문자열 자체가 그 분기가 아님을 증명 Rejected
H3 Receipt handle 만료(visibility timeout 초과) 후 SDK 가 ReceiptHandleIsInvalid 반환 이론적으로 가능 AWS 는 이 경우 HTTP 400 + InvalidParameterValue/ReceiptHandleIsInvalid 를 반환하지 socket hang up (전송 계층 에러) 을 반환하지 않음. 또한 QueueVisibilityTimeout = 600s 로 여유가 큼 Rejected
H4 코드 결함 — 재시도 로직 부재로 인한 반복 실패 aws-sdk v2 의 maxRetries=5, retryDelayOptions.base=10000 이 명시적으로 설정되어 있음 (aws-queue.manager.ts:17-21). 재시도가 이미 5회 수행된 후 실패한 것 Rejected
H5 다른 downstream 서비스(예: tesla API) 장애의 파생 같은 서비스에서 18:14:33/45 ECONNRESET 이 tesla API 가 아닌 SQS IP 대상 IP 대역이 AWS SQS 리전 IP 로 명확히 매핑됨. Tesla API 관련 504 는 별건(18:12:31)이며 시각이 다름 Rejected

Fix Recommendation#

즉시 조치 (Critical)#

없음. 이번 이벤트는 AWS 리전 네트워크의 일시적 flap 이며 서비스 코드 결함이 아니다. SDK 자체 재시도가 이미 5회 수행된 후 실패했고, 12초 후 동일 큐 delete 가 성공했으므로 즉시 배포/재기동이 필요한 상황이 아니다. 실패한 메시지는 SQS visibility timeout 만료 후 재수신되어 재처리되거나 MaxReceiveCount 도달 시 DLQ 로 이동한다.

단기 개선 (1주 이내)#

  1. 로그 severity 정합성 검토packages/base/src/manager/aws-queue.manager.ts:99logger.error(...) 는 SDK 재시도가 모두 소진된 최종 실패에서만 호출되지만, socket hang up 같은 transient network 실패도 error 로 남는다. err.code (예: NetworkingError, TimeoutError, ECONNRESET) 를 확인해 transient 계열은 warn 으로 다운그레이드하고 real error 만 error 로 남기는 방안을 고려. 방향만 제시, 코드 변경은 요구되지 않음 — 다른 서비스와의 로깅 컨벤션 확인 필요.
  2. DeleteMessage 실패의 caller-level 처리 재확인BaseService::checkingQueue (base-service.ts:107-111) 가 error 를 잡아 handlingMessageErrors 로 넘긴다. handlingMessageErrorsgetApiErrorToDeleteMessage 로 nodejs system error (err.errno && err.code && err.syscall) 를 감지해 warn 만 남기고 종료한다 (base-service.ts:245-248). 이번 케이스가 그 분기에 정확히 걸리는지 별도 로그로 확인 필요 — needs verification.

장기 개선 (재발 방지)#

  1. ap-southeast-2 리전 SQS 엔드포인트에 대한 별도 헬스체크/가용성 대시보드 도입. 이번처럼 SDK 자체 재시도 안에 flap 이 흡수되지 못하는 경우에 대비.
  2. AwsQueueManagerdeleteMessage / getQueueAttributes / receiveMessage 세 경로에서 발생하는 NetworkingError 를 카운터로 집계해 리전 flap 을 조기 감지.

Monitoring#

writing-datadog-monitoring-queries 가이드에 따라 timeseries widget 에 그대로 넣을 수 있는 문법으로 작성.

Rate of deleteMessage errors (서비스/리전별):

text
sum:datadog.estimated_usage.logs.ingested_events{service:cupixworks-capture-postprocessor-agent,status:error,@message:"AwsQueueManager::deleteMessage*"}.as_count()

간단히 로그 count 로 대체하려면 (Datadog Log Explorer analytics query 를 timeseries 로 사용):

text
logs("service:cupixworks-capture-postprocessor-agent status:error \"AwsQueueManager::deleteMessage\"").index("*").rollup("count").by("region")

Rate of transient network warnings (조기 감지):

text
logs("service:cupixworks-capture-postprocessor-agent status:warn (\"ECONNRESET\" OR \"socket hang up\")").index("*").rollup("count").by("region")

임계값 제안: 5분 창에 위 warn 카운트가 3회 이상이면 리전 flap 의심 알림.

Risk Assessment#

  • Risk level: low — 단발성 발생(14일 창에 1건), 자체 회복, SQS 재수신으로 데이터 손실 없음.
  • 예상 복잡도: trivial — 코드 변경 불필요. 필요시 로그 severity 조정 정도의 소폭 개선만 검토.