Api::V1::LinksController#create (avg 1832ms, max 1832ms)
RCA: Api::V1::LinksController#create Latency (1832ms)
Overview#
What Happened#
2026-05-26 06:32Z에 cupixworks-api 서비스의 Api::V1::LinksController#create 엔드포인트가 1832ms 응답 시간을 기록했다. DB 시간은 1.66ms에 불과했으며, 전체 지연은 외부 CupixGo 서비스에 대한 동기 HTTP 호출에서 발생했다. 이 패턴은 모든 리전에서 일관되게 ~1800-1900ms로 반복되고 있어 시스템적 문제이다.
Quick Facts#
| Field | Value |
|---|---|
| resource_name | Api::V1::LinksController#create |
| top_frame | app/controllers/api/v1/links_controller.rb:11 |
| env | production, us-west-2 |
| deploy | production-us-west-2-20260526t0459z0-dd7bd097-cupixworks |
| duration | 1832ms (DB: 1.66ms, View: 0.12ms) |
Timeline#
- 2026-05-26 06:32:39Z — LinksController#create 요청 시작 (user: mark.lee@cupix.com)
- 2026-05-26 06:32:42Z — 응답 완료 (HTTP 200, 1830.51ms)
- 2026-05-26 06:33:18Z — 동일 사용자 후속 요청 243ms로 정상 응답
Error Log#
{
"resource_name": "Api::V1::LinksController#create",
"service": "cupixworks-api",
"occurrences": 1,
"avg_ms": 1832,
"max_ms": 1832,
"sample_trace_id": "756110360056982764"
}
Impact#
- Service:
cupixworks-api - 발생 횟수: 1 (이번 클러스터), 다만 최근 30시간 동안 모든 호출에서 동일 패턴 반복
- 최초 발생: 2026-05-26T06:32:39.064Z
- 최근 발생: 2026-05-26T06:32:39.064Z
- 영향 범위: 링크 생성(URL 단축) 기능을 사용하는 모든 사용자 (모든 리전)
Root Cause Summary#
LinksController#create는 CupixGo 외부 서비스(go.{APP_HOST}/api/v1)에 동기 HTTP 요청을 보내 URL 단축 링크를 생성한다. 이 외부 서비스의 응답 시간이 일관되게 ~1800ms로 느려, 전체 API 응답 시간이 그대로 영향을 받는다. DB 쿼리(1.66ms)나 뷰 렌더링(0.12ms)은 무시할 수 있는 수준이며, 1830ms 전부가 외부 서비스 대기 시간이다. 이는 특정 시점의 일시적 문제가 아니라, 여러 리전(us-west-2, ap-southeast-2, ap-southeast-1)과 호스트에서 동일하게 재현되는 시스템적 문제이다.
Technical Analysis#
Code Path#
- Entry point:
app/controllers/api/v1/links_controller.rb:4(createaction) - External call:
app/controllers/api/v1/links_controller.rb:11(api_instance.link_create_link) - API client setup:
app/controllers/api/v1/links_controller.rb:51-65(api_instancemethod)
def create
create_link_request = CupixGo::CreateLinkRequest.new(
url: params[:url],
key: params[:key]
)
begin
result = api_instance.link_create_link(create_link_request) # ← 1830ms 소요
rescue CupixGo::ApiError => e
if [400, 401, 403].include?(e.code)
raise Cupix::Errors::Parameter.new(code: 'PRM12000', reason: e.to_s, message: e.message)
end
raise Cupix::Errors::System.new(code: 'SYS10000', reason: e.to_s, message: e.message)
else
render_json 200, {
shorten_url: "#{@schema}://#{$CONFIG[:cupix_go_host]}/#{result.key}"
}
end
end
def api_instance
configuration = CupixGo::Configuration.new do |config|
config.host = "#{$CONFIG[:cupix_go_host]}/api/v1"
config.scheme = $CONFIG[:cupix_go_scheme] || 'https'
end
configuration.class_eval do
def base_url(operation = nil)
"#{scheme}://#{[host, base_path].join('/').gsub(%r{/+}, '/')}".sub(%r{/+\z}, '')
end
end
api_client = CupixGo::ApiClient.new(configuration)
api_client.config.access_token = request.headers['x-cupix-auth']
CupixGo::LinkApi.new(api_client)
end
실행 흐름:
create액션이CupixGo::CreateLinkRequest객체를 생성 (즉시 완료)api_instance메서드가 매 요청마다 새로운 Configuration, ApiClient, LinkApi 인스턴스를 생성 (connection pooling 없음)link_create_link가https://go.{APP_HOST}/api/v1로 동기 HTTP POST 요청 전송- CupixGo 서비스가 ~1800ms 후에 응답 반환
- 응답을 받아
shorten_url로 렌더링
기대 동작: 링크 생성은 단순 CRUD 작업으로 100-300ms 이내 응답이 기대됨 실제 동작: CupixGo 서비스 응답 대기로 인해 1800-1900ms 일관 소요
Log Evidence#
Datadog 검색 쿼리:
service:cupixworks-api @http.url_details.path:"/api/v1/links" @duration:>500000000
핵심 로그 (대표 요청):
{
"timestamp": "2026-05-26T06:32:42.355Z",
"message": "[200] POST /api/v1/links (Api::V1::LinksController#create)",
"duration_ms": 1830.51,
"db_ms": 1.66,
"view_ms": 0.12,
"host": "ip-10-1-19-190.us-west-2.compute.internal",
"request_id": "f230bcfe-d8cd-4313-929e-3760f964b1a4",
"user": "mark.lee@cupix.com",
"params": {"key": "daidan-sv0giv"}
}
여러 리전에서의 일관된 지연 패턴:
2026-05-26T06:32:42Z | us-west-2 | 1830.51ms | DB 1.66ms
2026-05-25T21:31:06Z | ap-southeast-2 | 1867.73ms | DB 13.13ms
2026-05-25T16:50:55Z | us-west-2 | 1795.22ms | DB 2.10ms
2026-05-25T05:05:19Z | ap-southeast-2 | 1885.00ms | DB 2.64ms
2026-05-25T04:58:04Z | ap-southeast-1 | 1851.49ms | DB 2.44ms
모든 요청에서 DB 시간은 무시 가능(1-13ms)하며, 전체 1800-1900ms가 외부 서비스 호출에 소요됨.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | CupixGo 외부 서비스의 높은 기본 응답 시간이 원인 | 모든 리전에서 일관된 ~1800ms, DB/View 시간 무시 가능, 코드에서 동기 HTTP 호출 확인 (links_controller.rb:11) |
— | Confirmed |
| H2 | DB 쿼리 지연 또는 lock contention | — | DB 시간 1.66ms로 극히 짧음, 동일 호스트의 다른 요청도 DB 시간과 무관한 지연 | Rejected |
| H3 | 호스트 과부하로 인한 CPU/메모리 경합 | 동일 시간대 호스트에서 여러 느린 요청 존재 | 다른 리전/호스트에서도 동일 패턴(~1800ms), 호스트별 차이 없음 | Rejected |
| H4 | API Client 인스턴스 재생성 오버헤드 | 매 요청마다 Configuration/ApiClient/LinkApi 새로 생성, class_eval 메타프로그래밍 사용 |
객체 생성은 수 ms 수준, 1800ms를 설명하기에 부족 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- CupixGo 서비스(
go.{APP_HOST}) 자체의 응답 시간을 조사해야 한다. 서비스 내부에서 왜 ~1800ms가 걸리는지 확인 필요. - CupixGo 서비스에 대한 APM 트레이싱 또는 health check 추가하여 내부 병목 지점 파악.
단기 개선 (1주 이내)#
api_instance메서드에서 매 요청마다 새로 생성하는 대신 connection pooling 또는 persistent HTTP connection을 활용하도록 변경. TLS handshake 오버헤드가 반복되고 있을 가능성.- CupixGo API 호출에 timeout 설정 추가 (현재 timeout 없이 무한 대기 가능). 예:
open_timeout: 5,read_timeout: 5. links_controller.rb:56-60의class_eval메타프로그래밍을 제거하고, CupixGo gem 설정을 initializer에서 한 번만 수행하도록 리팩터링.
장기 개선 (재발 방지)#
- 링크 생성을 비동기 처리로 전환 검토: 클라이언트에 즉시 응답하고, 백그라운드에서 CupixGo 호출 후 결과를 push/poll 방식으로 전달.
- CupixGo 서비스 자체의 성능 최적화 (내부 아키텍처 검토 필요).
- 외부 서비스 호출이 있는 모든 컨트롤러에 대해 timeout 정책과 circuit breaker 패턴 적용.
Monitoring#
- CupixGo 서비스 응답 시간 메트릭 추가
- LinksController#create p95/p99 latency 알림 설정
service:cupixworks-api resource_name:"Api::V1::LinksController#create" @duration:>1000000000
- CupixGo 서비스 자체의 APM 트레이싱 도입으로 내부 병목 모니터링
Risk Assessment#
- Risk level: low (기능 자체는 정상 동작, HTTP 200 응답)
- 예상 복잡도: standard (CupixGo 서비스 내부 조사 필요, timeout/pooling 추가는 간단)