중급3분 분량

DynamoDB TTL

TTL(Time to Live)은 DynamoDB가 항목에 저장해둔 타임스탬프가 지나면 자동으로 항목을 삭제하게 해줍니다. Unix-epoch 만료 시각을 담는 속성 하나를 지정하면, DynamoDB가 백그라운드에서 만료된 항목을 수거합니다 — 별도의 수거 작업도, 추가 비용도 없습니다.

감사 로그 시나리오에서 각 테넌트에는 보존 정책이 있습니다: 이벤트를 90일, 또는 1년, 또는 규정 준수가 까다로운 경우 7년 동안 유지하기. TTL은 직접 삭제 스윕을 실행하지 않고 그것을 강제하는 방법입니다.

DynamoDB TTL은 어떻게 작동하나요?

DynamoDB TTL은 지정된 속성에 저장한 Unix-epoch(초) 타임스탬프가 지나면 항목을 자동으로 삭제합니다. 테이블에서 TTL을 활성화하고 만료 속성 이름을 지정하면, DynamoDB가 백그라운드에서 만료된 항목을 수거합니다 — 보통 48시간 이내이며, 쓰기 용량 비용은 없습니다. 만료된 항목은 실제로 삭제될 때까지 읽기에 계속 나타납니다.

  • TTL은 Unix-epoch(초) 타임스탬프를 담는 속성 하나입니다. 그 시각이 지나면 항목이 삭제 대상이 됩니다.
  • 삭제는 백그라운드이며 최선 노력(best-effort)입니다 — 보통 만료 후 며칠 이내이며 정확한 초는 아닙니다. AWS는 48시간 이내를 목표로 합니다.
  • TTL 삭제는 무료입니다 — 쓰기 용량을 소비하지 않습니다.
  • 만료되었지만 아직 삭제되지 않은 항목은 여전히 읽기에 나타나므로, 즉시 숨겨야 한다면 만료 속성에 대해 필터링하세요.

문제: 오래된 데이터를 직접 만료시키는 것은 비싸다

TTL이 없으면 "90일보다 오래된 이벤트를 버려라"를 강제하는 것은 직접 수거기를 실행한다는 뜻입니다: 일정에 따라 오래된 항목을 스캔(또는 쿼리)하고 각각을 DeleteItem하기. 그 스캔은 읽기 용량을 태우고, 삭제는 쓰기 용량을 태우며, 일정과 실패와 재시도를 당신이 떠안습니다.

대용량 감사 로그에서 이는 그저 데이터를 버리기 위한, 지속적이고 커져가는 세금입니다. TTL은 그 일 전체를 DynamoDB로, 무료로 옮깁니다.

TTL의 작동 방식

테이블에서 TTL을 활성화하고 어느 속성이 만료를 담는지 알려줍니다. AWS 발표에 따르면, "Unix epoch 만료 타임스탬프를 담는 항목 속성을 지정하면, DynamoDB가 테이블 성능에 영향을 주지 않고 백그라운드에서 삭제를 자동으로 처리"합니다.

정확성을 위해 두 가지 속성이 중요합니다:

  • 최선 노력이며 정확하지 않습니다. DynamoDB는 만료된 항목을 스캔하여 백그라운드에서 삭제하며, AWS는 만료 후 48시간 이내 삭제를 목표로 합니다. 항목은 그 타임스탬프에 대상이 되지만 잠시 남아 있을 수 있습니다.
  • 만료된 항목은 수거되기 전까지 여전히 읽을 수 있습니다. Query는 TTL이 지났지만 아직 삭제되지 않은 항목을 반환할 수 있습니다 — 따라서 "만료 = 즉시 비가시"가 엄격한 요구사항이라면 만료 속성에 FilterExpression을 추가하세요.

그리고 TTL 삭제는 쓰기 용량을 소비하지 않으며, 이것이 직접 실행하는 수거기보다 엄격히 더 저렴한 이유입니다.

실전 예시: 테넌트별 보존

각 감사 이벤트는 이벤트가 쓰여질 때 설정되는 expiresAt 속성을 담습니다 — 현재 + 테넌트의 보존 기간을 epoch 초로 나타낸 값입니다:

PKSKactionexpiresAtnote
TENANT#acmeEVENT#2026-03-26T…#a0login.success175887360090-day tenant: eligible now
TENANT#acmeEVENT#2026-06-24T…#a1invoice.export1766620800still inside window
TENANT#globex EVENT#2026-06-24T…#b9role.granted17981568007-year compliance tenant

expiresAt을 TTL 속성으로 하여 TTL을 활성화합니다. acme의 90일 이벤트가 1758873600을 넘으면, DynamoDB가 대략 이틀 이내에 스스로 그것을 삭제합니다. 규정 준수 테넌트의 이벤트는 먼 미래의 expiresAt을 담으므로 살아남습니다 — 같은 테이블, 같은 메커니즘, 항목별로 다른 보존.

쓰기 측면은 이벤트를 생성할 때 숫자 하나를 더하는 것뿐입니다. DynamoDB Expression Builder에서 SET expiresAt = :ttl 절을 조합하고 타입이 지정된 :ttl 값을 검증할 수 있습니다.

만료되었지만 수거되지 않은 이벤트를 읽기에서 즉시 숨기려면, 쿼리의 FilterExpressionexpiresAt > :now를 추가하세요 — 다만 필터는 읽기 비용을 줄이지 않는다는 점을 기억하세요(Query vs Scan).

DynoTable에서 해보기

전형적인 TTL 버그는 잘못된 expiresAt입니다: 초 대신 밀리초로 저장하거나 ISO 문자열로 저장하여, 항목이 결코 만료되지 않거나 즉시 사라지는 것입니다. 이를 잡는 유일한 방법은 실제로 저장된 값과 그 타입을 들여다보는 것입니다.

DynoTable은 각 항목의 속성을 그 DynamoDB 타입과 함께 보여주므로, 실제 보존을 TTL에 맡기기 전에 expiresAt이 — String도 밀리초도 아닌 — epoch 의 Number인지 확인할 수 있습니다.

DynoTable에서 감사 이벤트의 expiresAt 속성이 TTL이 작동하는 유일한 값인 Unix-epoch 초의 Number인지 검증하는 모습.
DynoTable에서 감사 이벤트의 expiresAt 속성이 TTL이 작동하는 유일한 값인 Unix-epoch 초의 Number인지 검증하는 모습.

함정과 다음 단계

  • epoch 초, Number로. 이것이 가장 흔한 단일 TTL 실수입니다. 밀리초 값은 만료를 약 50,000년 뒤로 밀어내고, ISO 문자열은 완전히 무시됩니다. 타입과 단위를 검증하세요.
  • 삭제 타이밍에 의존하지 마세요. 만료와 삭제 사이에 최대 약 48시간이 지날 수 있습니다. "만료되는 순간 사라짐"이 중요하다면 읽기에서 속성에 대해 필터링하세요. 행이 물리적으로 사라졌다고 가정하지 마세요.
  • TTL 삭제는 Streams에 나타납니다. TTL 삭제는 시스템 생성으로 표시된 스트림 레코드를 내보냅니다 — 만료되는 이벤트가 사라지기 전에 S3로 아카이브하는 표준 훅입니다. DynamoDB Streams를 참고하세요.
  • TTL 삭제는 GSI에도 적용됩니다. 항목을 제거하면 그것이 속해 있던 모든 보조 인덱스에서도 제거됩니다 — 이는 의도된 정리이지만, 인덱스가 카운트를 이끌었다면 알아둘 가치가 있습니다.

TTL은 이벤트 수명의 끝을 저렴하게 처리합니다. 다음 질문은 애초에 그 쓰기에 대해 무엇을 지불하느냐입니다 — 온디맨드 vs 프로비저닝 용량.

TTL을 켜기 전에 항목의 속성 타입을 검사하고 TTL 속성이 Unix-epoch Number인지 확인하려면 DynoTable을 다운로드하세요.

업데이트됨