Api::V1::BimRevisionsController#create_bim_revision_upload_credentials (avg 1076ms, max 1076ms)
RCA: BimRevisionsController#create_bim_revision_upload_credentials Latency (1076ms)
Overview#
What Happened#
2026-05-26 04:47 UTC, ap-southeast-2 리전의 cupixworks-api에서 BimRevisionsController#create_bim_revision_upload_credentials 엔드포인트가 1076ms의 응답 시간을 기록했다. 정상 응답 시간(~120ms) 대비 약 9배 느린 성능이며, 특정 사용자(nathan.love@multiplex.global)에게 반복적으로 발생하는 패턴이다.
Quick Facts#
| Field | Value |
|---|---|
| resource_name | Api::V1::BimRevisionsController#create_bim_revision_upload_credentials |
| top_frame | app/services/cupix/storage_service.rb:138 |
| env | production, ap-southeast-2 |
| deploy | production-ap-southeast-2-20260526t0356z0-3e770a15-cupixworks |
| avg_duration | 1076ms |
| db_time | 8.15ms |
Timeline#
- 2026-05-24 22:33 UTC — 동일 사용자에서 첫 slow request 관측 (1084ms, 1094ms)
- 2026-05-26 04:46:57 UTC — 795ms 응답 (같은 사용자, 다른 호스트)
- 2026-05-26 04:47:09 UTC — 1075ms 응답 기록, 클러스터 감지
Error Log#
{
"resource_name": "Api::V1::BimRevisionsController#create_bim_revision_upload_credentials",
"service": "cupixworks-api",
"occurrences": 1,
"avg_ms": 1076,
"max_ms": 1076,
"sample_trace_id": "338384434465347285"
}
Impact#
- Service:
cupixworks-api - 발생 횟수: 1 (클러스터 기준), 4건 (과거 포함)
- 최초 발생: 2026-05-26T04:47:06.797Z
- 최근 발생: 2026-05-26T04:47:06.797Z
- 영향 범위: multiplex-global 팀의 BIM 파일 업로드 UX 저하 (사용자 대기 시간 증가)
Root Cause Summary#
create_bim_revision_upload_credentials 엔드포인트에서 AWS STS get_federation_token API를 호출하여 임시 업로드 자격증명을 생성하는데, 이 외부 API 호출이 ap-southeast-2 리전에서 약 800-1000ms의 지연을 발생시킨다. Aws::STS::Client가 매 요청마다 새로 생성되며(connection pooling 없음), 자격증명 결과도 캐싱되지 않아 모든 요청이 full round-trip을 수행한다. DB 시간은 8ms에 불과하므로 나머지 ~1050ms가 STS API 호출에 소비된다.
Technical Analysis#
Code Path#
- Entry point:
app/controllers/api/v1/bim_revisions_controller.rb:46 - Repository delegation:
app/repositories/bim_revision_repository.rb:92 - Model method (state transition + credential 생성):
app/models/concerns/bim_revision_result/s3.rb:40 - Failure point (latency source):
app/services/cupix/storage_service.rb:138—client.get_federation_token(opts)
Controller action은 단순히 repository에 위임한다:
def create_bim_revision_upload_credentials
credentials = repository_instance.create_bim_revision_upload_credentials
render_json 200, credentials
end
Repository에서 권한 확인 후 model 메서드를 호출한다:
def create_bim_revision_upload_credentials
raise Cupix::Errors::PermissionDenied... unless @model.updatable_by?(self.current_user)
@model.bim_revision_upload_credentials
end
Model 메서드에서 state machine 전환 후 STS 호출을 수행한다:
def bim_revision_upload_credentials
self.uploading_bim_revision_state # State machine -> DB save
Cupix::StorageService.upload_credentials(
storage_option: storage_option,
id: id,
bucket_name: storage_option.s3_hosting_bucket_name,
key: bim_revision_basepath(bim_revision_upload_revision)
)
end
핵심 지연 원인 — 매 요청마다 새 STS client를 생성하고 get_federation_token을 호출한다:
def sts_client(storage_option: nil, **kwargs)
opts = parse_storage_option(storage_option).merge(kwargs)
Aws::STS::Client.new(opts) # 매번 새 인스턴스 생성, connection pooling 없음
end
def get_credential_token(storage_option: nil, **kwargs)
client = sts_client(storage_option: storage_option)
opts = kwargs
opts[:duration_seconds] ||= 7200
check_required_params(opts, %i[policy name duration_seconds])
begin
if storage_option.bucket_type == 'minio'
opts[:role_arn] = 'arn:xxx:xxx:xxx:xxxx'
opts[:role_session_name] = opts[:name]
opts.delete(:name)
resp = client.assume_role(opts)
else
resp = client.get_federation_token(opts) # <-- 800-1000ms 소요
end
rescue StandardError => e
raise Cupix::Errors::System.new(code: 'SYS20000', reason: "Can't create temporary token", message: e.message)
else
resp.credentials
end
end
upload_credentials 메서드에서 token name에 Time.now.to_i를 사용하므로 캐싱이 불가능하다:
token = get_credential_token(
storage_option: storage_option,
name: "#{Rails.env}-#{opts[:id]}-#{Time.now.to_i}", # 매초 고유한 name
policy: upload_credential_policy(opts[:bucket_name], opts[:key]),
duration_seconds: expiration_in.to_i # 4 hours
)
Log Evidence#
Datadog 쿼리로 동일 엔드포인트의 latency 패턴을 확인했다:
service:cupixworks-api resource_name:"Api::V1::BimRevisionsController#create_bim_revision_upload_credentials" env:production @http.status_code:200
slow request 로그 (nathan.love@multiplex.global):
{
"timestamp": "2026-05-26T04:47:09.522Z",
"duration_ms": 1074.94,
"db_runtime_ms": 8.15,
"host": "ip-10-1-17-211",
"http_method": "POST",
"path": "/api/v1/bim_revisions/4872/bim_revision_upload_credentials",
"status": 200,
"user": "nathan.love@multiplex.global",
"team": "multiplex-global",
"team_id": 157,
"user_agent": "cupix-agent",
"deploy": "production-ap-southeast-2-20260526t0356z0-3e770a15-cupixworks"
}
정상 request 비교 (다른 사용자, 같은 리전):
{
"timestamp": "2026-05-25T22:46:43Z",
"duration_ms": 125.31,
"db_runtime_ms": 19.38,
"host": "ip-10-1-145-251",
"user": "isha.singh@naylorlove.com.au",
"status": 200
}
패턴 분석:
nathan.love요청: 795-1094ms (DB 8-21ms) — STS 호출에 ~780-1070ms 소요- 다른 사용자 요청: 93-133ms (DB 12-28ms) — STS 호출이 ~70-100ms로 정상적
이 차이는 multiplex-global 팀의 storage_option 설정이 STS 응답 시간에 영향을 미치는 것으로 추정된다 (IAM policy 크기, cross-account 설정, 또는 STS endpoint 거리).
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | AWS STS get_federation_token 호출이 특정 팀의 storage_option 설정에서 높은 지연 발생 |
DB time 8ms vs total 1076ms = 외부 호출에 ~1050ms 소요. 같은 리전의 다른 사용자는 120ms 정상. nathan.love만 반복적 slow (5/24, 5/26). STS client가 매번 새로 생성됨 (storage_service.rb:17) |
같은 사용자도 가끔은 795ms (1076ms보다 낮음) — STS 응답 시간 변동성 | Confirmed |
| H2 | permission_joins의 복잡한 SQL 쿼리가 지연 원인 | bim_revision_repository에 11개 LEFT JOIN 존재 | DB runtime이 8-21ms로 매우 낮음. slow/normal 요청 모두 DB 시간 유사 | Rejected |
| H3 | Cognito get_user 인증 호출 지연 |
첫 요청 시 외부 호출 발생 가능 | 1시간 캐싱 적용됨. 해당 사용자는 연속 요청 중이므로 cache hit 확실 | Rejected |
| H4 | 인프라 문제 (특정 호스트 성능 저하) | — | slow request가 여러 호스트에서 발생 (ip-10-1-17-211, ip-10-1-145-251, ip-10-1-83-125) | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- 없음 — 이 latency는 기능적 오류가 아니며, 요청은 정상적으로 200 응답을 반환한다. 1076ms는 UX에 영향을 주지만 시스템 안정성에는 영향 없음.
단기 개선 (1주 이내)#
app/services/cupix/storage_service.rb:14-18: STS client를 singleton 또는 connection pool로 변경. 매 요청마다 새 TCP connection을 맺는 overhead를 제거.app/services/cupix/storage_service.rb:187-192: credential 캐싱 도입. 동일bim_revision_id와storage_option에 대해 token을 짧은 시간(예: 5분) 캐싱하여 연속 요청 시 STS 호출 회피. token name의Time.now.to_i를 time bucket(5분 단위)으로 변경.
장기 개선 (재발 방지)#
multiplex-global팀의storage_option설정 검토: cross-account access, IAM policy complexity 등이 STS 응답 시간에 영향을 줄 수 있으므로 팀별 storage 구성 감사.- APM에서 STS 호출을 별도 span으로 계측하여 리전별/팀별 STS latency를 가시화.
- 클라이언트 측에서 credential 재사용 여부 확인 —
cupix-agent가 매번 새 credential을 요청하는지, 기존 credential을 TTL 내에서 재사용하는지 점검.
Monitoring#
- STS 호출 latency 추적:
service:cupixworks-api resource_name:"Api::V1::BimRevisionsController#create_bim_revision_upload_credentials" env:production @duration:>500ms
- 팀별 latency 분포 알림:
avg(duration){service:cupixworks-api, resource_name:create_bim_revision_upload_credentials} by {team} > 500ms
Risk Assessment#
- Risk level: low
- 예상 복잡도: standard
- 이유: 기능적 오류는 아님 (200 응답). UX 저하에 해당하며, STS client pooling/caching 추가는 기존 동작에 영향을 최소화하면서 개선 가능.