ES /docs

API Gateway — 30s integration timeout exceeded by Athena query latency

RCA: failed to get validation data - error: 504 Gateway Timeout

Overview#

What Happened#

2026-04-26 22:26~23:06 UTC (약 40분간) cupixworks-api 서비스의 Cupix::SiteinsightsService#_get_element_record_counts 메서드에서 외부 AWS API Gateway Siteinsights 서비스 호출이 504 Gateway Timeout으로 실패했다. 단일 사용자(yohan.kim@cupix.com)가 3개 facility에 대해 반복 요청하면서 총 38건의 에러가 발생했으며, 클라이언트에는 HTTP 502 Bad Gateway로 응답되었다.

Quick Facts#

Field Value
exception.class RestClient::Exception (wrapped as Cupix::Errors::System)
exception.message failed to get validation data - error: 504 Gateway Timeout
top_frame app/services/cupix/siteinsights_service.rb:282
error_code SYS20000BG10005 (502)
env production, us-west-2
deploy 20260426T0631Z0, 20260424T1951Z0, 20260424T2039Z0

Affected Teams#

Team / Domain Error Count Impact
admin (team_id: 133) 38 Siteinsights validation 기능 사용 불가 — element record 정합성 검증 실패

Timeline#

  1. 2026-04-26T22:26:38Z — 최초 에러 발생 (facility umphr6)
  2. 2026-04-26T23:06:41Z — 마지막 에러 발생 (40분간 38건)
  3. 2026-04-27 — Error Sweeper 감지, RCA 수행

Error Log#

Datadog Logs

text
failed to get validation data - error: 504 Gateway Timeout

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 38
  • 최초 발생: 2026-04-26T22:26:38.972Z
  • 최근 발생: 2026-04-26T23:06:41.544Z
  • 영향 사용자: 1명 (yohan.kim@cupix.com, admin team)
  • 영향 facility: umphr6 (29건), 3fq7tj (8건), 10ofni (1건)
  • 영향 호스트: 3대 (us-west-2 인스턴스 전체)

Root Cause Summary#

Cupix::SiteinsightsService#_get_element_record_counts 메서드가 AWS API Gateway의 Siteinsights /element_records/validation 엔드포인트로 POST 요청을 보내는데, Lambda 함수 timeout(60초)과 API Gateway integration timeout(29초, 기본값)의 불일치로 504 Gateway Timeout이 반환되었다. ElementRecordProxyFunction Lambda는 template.yaml:651에서 Timeout: 60으로 설정되어 있으나, api.yaml:260-266의 API Gateway integration 정의에는 timeoutInMillis가 명시되지 않아 AWS 기본값 29초가 적용된다. Lambda가 29초 이상 처리에 소요되면 — Lambda 자체는 아직 60초 제한 내에서 실행 중이지만 — API Gateway가 먼저 504를 반환한다. 에러 로그의 request duration이 ~31.6초로 나타나는 점(DB time ~1.9초 + API Gateway 29초 timeout + 네트워크 오버헤드)이 이를 뒷받침한다. RestClient.post 호출에 명시적 timeout이 없고, retry 로직도 없어 모든 요청이 즉시 실패로 처리되었다.

Technical Analysis#

Code Path#

1. Entry point — Controller

app/controllers/api/v1/element_records_controller.rb:29-33ruby
def validation
  response = Cupix::SiteinsightsService.validate_element_records(params[:facility_key], current_user: @current_user, current_team: @current_team)

  render_json 200, response
end

클라이언트의 GET /api/v1/siteinsights/element_records/validation 요청을 처리한다.

2. Service orchestration

app/services/cupix/siteinsights_service.rb:196-212ruby
def validate_element_records(facility_key, current_user: nil, current_team: nil)
  raise Cupix::Errors::Parameter.new(code: 'ARG10000', reason: 'facility_key is required') if facility_key.blank?

  facility = ::FacilityRepository.new(current_user: current_user, current_team: current_team).show(facility_key)

  element_counts = _calculate_element_counts(facility)

  element_record_counts = _get_element_record_counts(facility_key, element_counts[:tasks_for_query])

  stale_elements = _get_stale_elements_if_needed(facility, facility_key, element_record_counts)

  result = _build_validation_result(facility_key, element_counts, element_record_counts, stale_elements)

  Cupix::Logger.info('validate_element_records completed', class: self.name, function: __method__, facility_key: facility_key, is_valid: result[:is_valid], summary: result[:summary])

  result
end

DB 조회 후 외부 서비스를 호출하는 순차적 흐름이다. _get_element_record_counts에서 에러가 발생하면 이후 로직이 모두 실행되지 않는다.

3. Failure point — 외부 API 호출

app/services/cupix/siteinsights_service.rb:272-287ruby
def _get_element_record_counts(facility_key, tasks_for_query)
  return _empty_element_record_counts if tasks_for_query.empty?

  response = RestClient.post(
    "#{Cupix::Siteinsights.service_url}/element_records/validation",
    { facility_key: facility_key, tasks: tasks_for_query }.to_json,
    content_type: :json
  )
  JSON.parse(response.body)['result']['data']
rescue RestClient::Exception => e
  Cupix::Logger.error("failed to get validation data - error: #{e.message}", class: self.name, function: __method__, facility_key: facility_key)
  raise Cupix::Errors::System.new(code: 'SYS20000', reason: "failed to get validation data - error: #{e.message}")
rescue JSON::ParserError => e
  Cupix::Logger.error("failed to parse response body - error: #{e.message}", class: self.name, function: __method__, facility_key: facility_key)
  raise Cupix::Errors::System.new(code: 'SYS20000', reason: "failed to parse response body - error: #{e.message}")
end

RestClient.posttimeout 파라미터가 없다. AWS API Gateway는 기본 integration timeout이 29초이며, 백엔드(Lambda 또는 다른 서비스)가 이 시간 내에 응답하지 못하면 504를 반환한다.

4. Lambda / API Gateway Timeout 설정 불일치

/element_records/validation 엔드포인트를 처리하는 Lambda는 ElementRecordProxyFunction이다:

applications/siteinsights-service/template.yaml:646-652yaml
ElementRecordProxyFunction:
  Type: AWS::Serverless::Function
  Properties:
    Handler: functions/api/ElementRecord.handler
    FunctionName: !Sub "${Tenant}-${Environment}-${ServiceName}-ElementRecordProxy"
    Timeout: 60
    MemorySize: 1024

Lambda timeout은 60초로 설정되어 있다. 한편, API Gateway의 integration 정의에는 timeoutInMillis가 명시되어 있지 않다:

applications/siteinsights-service/api.yaml:260-266yaml
x-amazon-apigateway-integration:
  type: "aws_proxy"
  uri:
    Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ElementRecordProxyFunction.Arn}/invocations"
  httpMethod: "POST"
  passThroughBehavior: "when_no_match"
  payloadFormatVersion: "2.0"

AWS API Gateway REST API의 기본 integration timeout은 29초이다. 따라서 Lambda(60초)가 처리 중이더라도 API Gateway(29초)가 먼저 timeout을 반환하는 구조적 불일치가 존재한다.

Component Timeout Source
ElementRecordProxyFunction Lambda 60s template.yaml:651
API Gateway integration (기본값) 29s api.yaml:260-266timeoutInMillis 미설정
RestClient.post (cupixworks-api) ∞ (기본) siteinsights_service.rb:275-279 — timeout 미설정

5. Service URL configuration

lib/cupix/siteinsights.rb:4-30ruby
def service_url
  case Cupix::Tesla.tenant
  when 'cupix'
    case Rails.env
    when 'production'
      case Cupix::Tesla.region_code
      # ...
      else
        'https://6hdi0xzqqk.execute-api.us-west-2.amazonaws.com/api'
      end
    end
  end
end

us-west-2 production 환경에서는 https://6hdi0xzqqk.execute-api.us-west-2.amazonaws.com/api/element_records/validation으로 호출한다.

6. 에러 전파 — Controller rescue

app/controllers/api/v1/element_records_controller.rb:37-39ruby
def redirect_to_502_error(exception)
  raise_error(502, exception, code: 'BG10005', type: Cupix::Errors::BadGateway, reason: 'BadGateway', message: exception.message)
end

SYS20000 에러가 controller에서 502 Bad Gateway(BG10005)로 변환되어 클라이언트에 반환된다.

Log Evidence#

Datadog 검색 쿼리 — application error logs:

text
service:cupixworks-api status:error "failed to get validation data"

38건의 동일한 에러 로그가 확인되었다. 모든 로그의 속성:

json
{
  "message": "failed to get validation data - error: 504 Gateway Timeout",
  "class": "Cupix::SiteinsightsService",
  "function": "_get_element_record_counts",
  "facility_key": "umphr6",
  "log_type": "custom"
}

Datadog 검색 쿼리 — request logs:

text
service:cupixworks-api "504"

39건의 request log가 확인되었으며 핵심 속성:

json
{
  "controller": "Api::V1::ElementRecordsController#validation",
  "status_code": 502,
  "error_class": "Cupix::Errors::System",
  "error_code": "SYS20000",
  "duration_ms": 31600,
  "db_time_ms": 1900,
  "user": "yohan.kim@cupix.com",
  "user_id": 5874,
  "auth_method": "COGNITO",
  "team_domain": "admin",
  "team_id": 133
}

request duration이 평균 ~31,600ms로 일관되게 나타난다. DB time은 ~1,900ms이므로, 외부 서비스 호출에서 약 29,700ms (≈ API Gateway의 29초 timeout + 네트워크 오버헤드)가 소비된 것으로 판단된다.

Cross-service 검색 — downstream 에러 확인:

text
"validation data" status:error

cupixworks-api 외에 다른 서비스에서는 관련 에러가 발견되지 않았다. Siteinsights 백엔드 서비스는 Datadog에 별도로 인덱싱되지 않는 것으로 보인다 (AWS API Gateway + Lambda 구조 추정).

동일 시간대 다른 에러 확인:

text
service:cupixworks-api status:error

해당 시간 윈도우(22:00~23:10 UTC)에서 이 validation 에러 외 다른 에러 유형은 없었다.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 Siteinsights Lambda timeout(60s)과 API Gateway integration timeout(29s)의 불일치로 Lambda 처리 중 API Gateway가 먼저 504 반환 template.yaml:651 Lambda Timeout: 60, api.yaml:260-266 timeoutInMillis 미설정(기본 29초). request duration ~31.6초가 API Gateway 29초 + 오버헤드에 정확히 부합. 3대 호스트, 3개 facility 모두 동일 패턴 Confirmed
H2 cupixworks-api 측 네트워크 문제로 인한 연결 실패 us-west-2의 3대 인스턴스 모두 동일하게 실패 504는 connection failure가 아닌 gateway timeout. duration이 일관되게 ~30초로 네트워크 단절 패턴이 아님. 같은 시간대에 다른 에러 없음 Rejected
H3 특정 facility의 대량 데이터로 인한 쿼리 성능 저하 umphr6 facility가 29/38건(76%)으로 가장 많이 실패 3fq7tj(8건), 10ofni(1건)도 실패. 3개 facility 모두 실패하므로 특정 데이터 문제가 아닌 서비스 전체 문제 Rejected
H4 RestClient 측 timeout 설정 부재로 인한 과도한 대기 코드에 명시적 timeout 미설정 (siteinsights_service.rb:275-279) 504는 API Gateway가 먼저 timeout을 반환한 것이므로, RestClient timeout과 무관하게 발생함. 다만 timeout 부재는 별도 개선 필요 Rejected (직접 원인 아님, 개선 필요)

Fix Recommendation#

즉시 조치 (Critical)#

504 발생의 구조적 원인은 Lambda timeout(60s)과 API Gateway integration timeout(29s, 기본값)의 불일치이다. 두 가지 방향으로 해결 가능하다:

  • 방안 A — API Gateway timeout 증가: api.yaml/element_records/validation integration에 timeoutInMillis: 60000을 추가하여 Lambda timeout(60s)과 일치시킨다. 단, API Gateway REST API의 최대 integration timeout은 29초이므로, 이를 넘기려면 API Gateway HTTP API로 전환하거나 다른 접근이 필요하다.
  • 방안 B — Lambda 처리 최적화: ElementRecordProxyFunction의 validation 로직이 29초 내에 완료되도록 최적화한다 (MongoDB 쿼리 최적화, 인덱스 검토 등).
  • app/services/cupix/siteinsights_service.rb:275-279: RestClient.post 호출에 명시적 timeoutopen_timeout 파라미터를 추가해야 한다. API Gateway의 29초 timeout보다 약간 긴 값(예: 35초)을 설정하여, API Gateway timeout 이후 불필요하게 대기하지 않도록 한다.
  • Siteinsights 백엔드 서비스 팀에 504 timeout 발생 사실을 공유하고, Lambda timeout vs API Gateway timeout 불일치 문제를 함께 검토해야 한다.

단기 개선 (1주 이내)#

  • retry 로직 추가: _get_element_record_counts에 exponential backoff를 적용한 retry를 1-2회 추가. 504는 일시적 문제일 수 있으므로 재시도가 효과적이다.
  • 에러 로그 레벨 검토: 외부 서비스 timeout은 transient한 운영 이슈일 수 있으므로, 첫 번째 시도 실패 시 warn, retry 후에도 실패 시 error로 로깅하는 방식을 고려한다.
  • Circuit breaker 패턴 검토: 동일 서비스에 대한 반복 실패 시 빠르게 fallback하여 클라이언트 대기 시간을 줄인다.

장기 개선 (재발 방지)#

  • Lambda/API Gateway timeout 정렬: template.yaml:651의 Lambda timeout(60s)과 api.yaml의 API Gateway integration timeout(기본 29s)을 일치시키는 정책을 수립한다. 다른 siteinsights 엔드포인트(GET /element_records, PUT /element_records/bulk 등)도 동일한 불일치가 있을 수 있으므로 전체 점검이 필요하다.
  • Siteinsights 백엔드 서비스의 성능 모니터링 및 auto-scaling 검토 (Lambda의 경우 concurrency limit, provisioned concurrency 등).
  • Siteinsights 서비스 로그를 Datadog에 인덱싱하여 end-to-end 추적 가능하도록 개선.

Monitoring#

  • Siteinsights 외부 호출 성능 모니터링:
text
service:cupixworks-api "Cupix::SiteinsightsService" status:error
  • Request duration 이상 감지 (p99 > 30초):
text
service:cupixworks-api @http.url_details.path:"/api/v1/siteinsights/element_records/validation" @duration:>30000000000
  • 504 에러 발생률 알림:
text
service:cupixworks-api "504 Gateway Timeout"

Risk Assessment#

  • Risk level: low — downstream 서비스의 일시적 성능 저하로 발생한 에러. 단일 사용자(admin)에게만 영향. 데이터 손실 없음.
  • 예상 복잡도: standard — timeout 설정 추가와 retry 로직은 비교적 간단하나, downstream 서비스 성능 개선은 별도 팀 협업 필요.

Revision History#

Revision 1#

Feedback: siteinsights service lambda timeout 이랑 api gateway timeout 이 다른지 확인해줘

판정:

피드백 항목 판정 근거
Lambda timeout과 API Gateway timeout이 다른지 확인 수용 다르다. ElementRecordProxyFunction Lambda timeout은 60초(template.yaml:651Timeout: 60), API Gateway integration timeout은 29초(기본값, api.yaml:260-266timeoutInMillis 미설정). Lambda는 60초까지 실행 가능하나 API Gateway가 29초에 먼저 504를 반환하는 구조적 불일치가 확인됨. 기존 RCA에서 "API Gateway 29초 timeout"만 언급하고 Lambda timeout과의 차이를 명시하지 않았던 부분을 보완.

변경 사항:

  • Root Cause Summary: Lambda timeout(60s)과 API Gateway integration timeout(29s) 불일치를 명시적으로 기술. template.yaml:651, api.yaml:260-266 코드 참조 추가.
  • Technical Analysis > Code Path: 새 섹션 "4. Lambda / API Gateway Timeout 설정 불일치" 추가 — Lambda 설정(template.yaml:646-652)과 API Gateway integration 설정(api.yaml:260-266)의 코드 스니펫 및 timeout 비교 테이블 포함.
  • Hypotheses Considered: H1을 timeout 불일치 가설로 구체화.
  • Fix Recommendation: API Gateway timeout 증가(방안 A)와 Lambda 처리 최적화(방안 B) 두 가지 방향을 제시. API Gateway REST API 최대 timeout(29초) 제약 사항 명시.
  • 장기 개선: 다른 siteinsights 엔드포인트에도 동일한 timeout 불일치가 있을 수 있으므로 전체 점검 권장.

추가 조사 내용:

  • cupixworks/applications/siteinsights-service/template.yaml — Lambda 함수 정의 및 timeout 설정 확인
  • cupixworks/applications/siteinsights-service/api.yaml — API Gateway OpenAPI 정의 및 integration 설정 확인 (timeoutInMillis 부재)
  • cupixworks/applications/siteinsights-service/api.anchored.yaml — 동일 endpoint의 anchored API 정의 교차 확인