안정성을 유지하면서 소프트웨어를 신속하게 배포하는 것은 끊임없이 상충하는 과제입니다. Databricks가 성장함에 따라 수백 개의 서비스, 여러 클라우드, 수천 개의 고객 워크로드에 걸쳐 변경 사항을 안전하게 롤아웃하는 복잡성도 증가했습니다. 기능 플래그는 코드를 배포하는 결정과 이를 활성화하는 결정을 분리하여 이러한 복잡성을 관리하는 데 도움이 됩니다. 이러한 분리를 통해 엔지니어는 배포 속도를 저하시키지 않으면서 장애를 격리하고 사고를 더 신속하게 완화할 수 있습니다.
Databricks의 안정성 상태를 구성하는 핵심 요소 중 하나는 "SAFE"라고 불리는 사내 기능 플래그 및 실험 플랫폼입니다. Databricks 엔지니어는 매일 SAFE를 사용하여 기능을 출시하고, 서 비스 동작을 동적으로 제어하며, A/B Experiment으로 기능의 효과를 측정합니다.
SAFE는 서비스 바이너리 릴리스와 기능 활성화를 완전히 분리하여 팀이 바이너리 배포와 독립적으로 기능을 출시할 수 있도록 한다는 '핵심 목표'를 가지고 시작되었습니다. 이를 통해 기능을 점진적으로 더 많은 사용자에게 안정적으로 확장하고, 출시로 인해 발생한 인시던트를 신속하게 완화하는 등 많은 부수적인 이점을 얻을 수 있습니다.
빠르게 성장하는 제품 표면적으로 여러 클라우드에 걸쳐 수천 개의 기업 고객에게 서비스를 제공하는 Databricks의 규모에서는 저희의 고유한 요구 사항을 충족할 수 있는 기능 플래그 시스템이 필요했습니다.
이러한 요구사항을 신중하게 고려한 후, 저희는 최종적으로 맞춤형 사내 기능 플래그 시스템을 구축하기로 결정했습니다. 저희는 아키텍처와 함께 발전할 수 있고, 수백 개의 서비스와 수천 명의 엔지니어에 걸쳐 플래그를 안전하게 관리하는 데 필요한 거버넌스 제어를 제공하는 솔루션이 필요했습니다. 확장성 및 안전성 목표를 성공적으로 달성하려면 인프라 데이터 모델, 서비스 프레임워크, CI 시스템과의 긴밀한 통합이 필요했습니다.
2025년 말 기준으로 SAFE에는 약 2만 5천 개의 활성 플래그가 있으며, 매주 4천 건의 플래그 전환이 이루어집니다. 피크 시 SAFE는 플래그 평가에 대해 약 10μs의 p95 지연 시간을 유지하면서 초당 3억 건 이상의 평가를 실행합니다.
이 게시물에서는 이러한 요구 사항을 충족하기 위해 SAFE를 구축한 방법과 그 과정에서 얻은 교훈을 살펴봅니다.
먼저 SAFE 플래그에 대한 일반적인 사용자 여정을 살펴보겠습니다. 기본적으로 기능 플래그는 외부 구성에서 제어되는 조건에 따라 다른 값을 가질 수 있으며 서비스의 제어 흐름에서 액세스할 수 있는 변수입니다. 기능 플래그의 매우 일반적인 사용 사례 중 하나는 처음에는 적은 양의 트래픽으로 시작하여 점차 전역으로 활성화하는 등 통제된 방식으로 새로운 코드 경로를 점진적으로 활성화하는 것입니다.
SAFE 사용자는 먼저 서비스 코드에서 플래그를 정의한 다음, 이를 새 기능의 로직에 대한 조건부 게이트로 사용합니다.
그러면 사용자는 내부 SAFE UI로 이동하여 이 플래그를 등록하고 플래그를 출시할 템플릿을 선택합니다. 이 템플릿은 정렬된 단계 목록으로 구성된 점진적 램프업 계획을 정의합니다. 각 단계는 백분율에 따라 점진적으로 확대됩니다. 플래그가 생성되면 사용자에게 다음과 같은 UI가 표시됩니다.
여기에서 사용자는 한 번에 한 단계씩 수동으로 플래그를 롤아웃하거나 플래그 플립이 자동으로 생성되도록 일정을 설정할 수 있습니다. 내부적으로 플래그 구성의 소스 오브 트루스(Source of Truth)는 Databricks 모노리포에 체크인된 jsonnet 파일로, 경량 도메인 특화 언어(DSL)를 사용하여 플래그 구성을 관리합니다.
사용자가 UI에서 플래그를 변경하면 해당 변경의 결과로 다른 엔지니어 한 명 이상의 검토가 필요한 풀 리퀘스트가 생성됩니다. SAFE는 또한 안전하지 않거나 의도하지 않은 변경을 방지하기 위해 다양한 merge 전 검사를 실행합니다. 변경 사항이 Merge되면 PR이 Merge된 후 2~5분 이내에 사용자의 서비스가 해당 변경 사항을 적용하고 새로운 값을 start합니다.
SAFE는 위에 설명된 기능 출시 사용 사례 외에도 수명이 긴 동적 구성(예: "과 같은 동적 서비스 구성의 다른 측면에도 사용됩니다. 시간 초과 또는 속도 제한), 인프라 마이그레이션을 위한 상태 머신 제어 또는 소규모 구성 블롭(예: 타겟 로깅 정책).

SAFE는 내부적으로 지원되는 여러 언어로 클라이언트 "SDK"를 제공하며, Scala SDK가 가장 성숙하고 널리 채택되었습니다. SDK는 기본적으로 구성 로딩 컴포넌트와 결합된 기준 평가 라이브러리입니다. 각 플래그에는 런타임에 SDK가 반환해야 하는 값을 제어하는 기준 집합이 있습니다. SDK는 최신 구성 세트 로드를 관리하며 런타임에 해당 기준을 평가한 결과를 신속하게 반환해야 합니다.
의사 코드에서 기준은 내부적으로 다음과 같이 표시됩니다.
기준은 일련의 불리언 표현식 트리와 유사한 것으로 모델링될 수 있습니다. 각 조건부 표현식은 빠른 결과를 반환하기 위해 효율적으로 평가되어야 합니다.
성능 요구 사항을 충족하기 위해 SAFE SDK 디자인은 (1) 구성 전달과 평가의 분리, (2) 정적 및 런타임 평가 차원의 분리라는 몇 가지 아키텍처 원칙을 구현합니다.
대규모 환경에서 1밀리초 미만의 평가 지연 시간을 안정적으로 달성하기 위해 SAFE는 정적인 부울 표현식 트리의 일부를 사전 평가합니다. SAFE 구성 번들이 서비스에 전달되면 SDK는 플래그 구성의 인메모리 표현에 대해 모든 정적 차원을 즉시 평가합니다. 이를 통해 해당 특정 서비스 인스턴스와 관련된 로직만 포함하는 단순화된 구성 트리가 생성됩니다.
요청 처리 중에 플래그 평가가 요청되면 SDK는 이 사전 컴파일된 구성에 대해 나머지 런타임 차원만 평가하면 됩니다. 이는 각 평가의 계산 비용을 크게 줄여줍니다. 많은 플래그가 불리언 표현식 트리에서 정적 차원만 사용하므로 사실상 전체 사전 평가가 가능합니다.
Databricks의 모든 서비스에 구성을 안정적으로 전달하기 위해 SAFE는 자체 개발한 동적 구성 전달 플랫폼인 Zippy와 긴밀하게 연동됩니다. Zippy 아키텍처에 대한 자세한 설명은 다른 게시물에서 다루기로 하고, 간단히 말해 Zippy는 다중 계층의 글로벌/리전 아키텍처와 클라우드별 Blob 스토리지를 사용하여 중앙 소스의 임의 구성 Blob을 Databricks Control Plane에서 실행되는 모든 Kubernetes Pod 등으로 전송합니다.

전달된 플래그의 수명 주기는 다음과 같습니다.
엔드투엔드(End-to-end)로 플래그 변경은 일반적으로 PR이 Merge된 후 3~5분 이내에 모든 서비스에 전파됩니다.
플래그 전달 파이프라인 내에서 플래그 구성은 여러 형태를 띠며, 플래그가 평가에 가까워질수록 상위 수준의 사람이 읽을 수 있는 시맨틱 구성에서 기계가 읽을 수 있는 간결한 버전으로 점진적으로 변환됩니다.
사용자 인터페이스에서는 맞춤형 DSL과 함께 Jsonnet을 사용하여 플래그가 정의되므로 임의로 복잡한 플래그 구성이 가능합니다. 이 DSL은 미리 정의된 템플릿을 사용하여 플래그 롤아웃을 구성하거나 트래픽 슬라이스에 대한 특정 재정의를 설정하는 것과 같은 일반적인 사용 사례를 위한 편의 기능을 제공합니다.
체크인되면 이 DSL은 구성의 시맨틱 의 도를 포착하는 내부 protobuf 등가물로 변환됩니다. 그런 다음 SAFE 백엔드는 이 시맨틱 구성을 부울 표현식 트리로 추가 변환합니다. 이 부울 표현식 트리의 protobuf 설명은 SAFE SDK에 전달되며, SDK는 이를 구성의 더욱 압축된 인메모리 표현으로 로드합니다.

대부분의 플래그 전환은 SAFE 플래그를 관리하기 위한 내부 UI에서 시작됩니다. 이 UI를 사용하면 간단한 변경을 위해 대부분의 Jsonnet 복잡성을 추상화하는 워크플로를 통해 플래그를 생성, 수정, 중단할 수 있으며, 고급 사용 사례를 위해 DSL의 거의 모든 강력한 기능에 계속 액세스할 수 있습니다.
또한 기능이 풍부한 UI 덕분에 플래그 전환 예약, merge 후 상태 확인 지원, 특정 리전 또는 서비스에 영향을 미친 최근 플래그 전환을 확인하는 디버깅 도구와 같은 추가적인 편의 기능도 제공할 수 있었습니다.
모든 SAFE 플래그 변경 사항은 일반적인 Github PR로 생성되며, 광범위한 사전 merge 유효성 검사기 세트를 사용하여 검증됩니다. 잠재적으로 안전하지 않은 플래그 변경으로부터 최상의 보호 방법을 터득함에 따라, 이 유효성 검사기 세트는 수십 개의 개별 검사를 포함하도록 확장되었습니다. SAFE 초기 도입 단계에서, SAFE 플래그 전환으로 인해 발생했거나 완화된 사고에 대한 사후 검토를 통해 이러한 검사 중 상당수가 만들어졌습니다. 예를 들어, 현재 저희는 영향 범위가 큰 변경에 대해 전문적인 검토를 요구하고, 플래그를 활성화하기 전에 특정 서 비스 바이너리 버전 배포를 요구하며, 미묘하고 일반적인 잘못된 구성 패턴을 방지하는 등의 검사 기능을 갖추고 있습니다.
팀은 또한 자체적인 플래그 또는 팀별 사전 병합 검사를 정의하여 구성의 불변성을 강제할 수 있습니다.
서비스 안정성에서 SAFE의 중요한 역할을 고려하여, 시스템은 딜리버리 파이프라인의 일부에 장애가 발생하더라도 지속적인 운영을 보장하기 위해 여러 계층의 복원력으로 설계되었습니다.
가장 일반적인 실패 시나리오는 구성 전달 경로의 타격을 포함합니다. 전달 경로에서 구성 업데이트에 실패하는 경우, 서비스는 전달 경로가 복원될 때까지 마지막으로 알려진 구성을 계속 제공합니다. 이 "정적 실패(fail static)" 접근 방식은 업스트림 중단 중에도 기존 서비스 동작이 안정적으로 유지되도록 보장합니다.
더 심각한 시나리오에 대비하여 다음과 같은 여러 폴백 메커니즘을 유지합니다.

SAFE SDK 자체 내에서 방어적 설계는 구성 오류의 영향 범위(blast radius)를 제한합니다. 특정 플래그의 구성이 잘못된 경우 해당 단일 플래그만 영향을 받습니다. 또한 SDK는 예외를 발생시키지 않고 항상 코드 기본값으로 페일 오픈(fail open)되는 계약을 유지하므로, 애플리케이션 개발자는 플래그 평가를 오류 발생 가능성이 있는 것으로 취급할 필요가 없습니다. 또한 SDK는 구성 구문 분석 또는 평가 오류가 발생하면 대기 중인 엔지니어에게 즉시 알립니다. SAFE의 성숙도와 광범위한 사전 merge 검증으로 인해 이제 프로덕션 환경에서 이러한 실패는 매우 드물게 발생합니다.
이러한 계층화된 복원력 접근 방식은 SAFE가 정상적으로 성능이 저하되도록 보장하고, 단일 장애점이 될 위험을 최소화합니다.
종속성 최소화와 계층화된 이중화 fallback은 운영 부담을 줄여줍니다. Databricks의 거의 모든 compute 환경에 배포되어 많이 사용됨에도 불구하고 SAFE를 유지 관리하는 데 따르는 운영 부담은 꽤 관리하기 쉬운 수준이었습니다. 콜드 스타트 번들 및 SDK의 "fail static" 동작과 같은 계층화된 이중화를 추가하여 SAFE 아키텍처의 많은 부분이 자가 치유되도록 했습니다.
개발자 경험이 가장 중요합니다. 견고한 플래그 시스템의 "인적 측면"을 확장하려면 강력한 UX 중심의 접근이 필요했습니다. SAFE는 장애를 완화하는 데 자주 사용되는 미션 크리티컬 시스템입니다. 따라서 비상시에 플래그를 전환하기 위한 사용자 친화적인 UX를 구축하는 것은 매우 효과적이었습니다. 제품 중심의 사고방식을 채택함으로써 사소한 문제와 혼란이 줄어들었고, 궁극적으로는 전사적인 장애 평균 복구 시간(MTTR)이 단축되었습니다.
"모범 사례"를 마찰이 적은 경로로 만드세요. 가장 큰 교훈 중 하나는 모범 사례를 문서화하기만 하고 엔지니어들이 이를 따를 것으로 기대할 수는 없다는 것이었습니다. 엔지니어들은 기능을 출시할 때 여러 상충하는 우선순위를 가집니다. SAFE는 안전한 길을 쉬운 길로 만듭니다. 즉, 점진적 롤아웃은 더 위험한 활성화 패턴보다 노력이 덜 들고 더 많은 삶의 질 향상 기능을 사용할 수 있습니다. 시스템이 더 안전한 행동을 장려할 때, 플랫폼은 엔지니어들이 책임감 있는 변경 관리 문화를 갖도록 유도할 수 있습니다.
SAFE는 이제 Databricks 내에서 안정화된 내부 플랫폼으로 널리 사용되고 있습니다. SAFE 플래그 사용을 통해 평균 해결 시간과 프로덕션 인시던트의 영향 반경이 모두 지속적으로 감소하는 것을 보며, 가용성과 개발자 경험에 대한 투자가 결실을 보고 있습니다.
Databricks의 제품 영역이 계속 확장됨에 따라, 해당 제품의 기반이 되는 인프라 프리미티브는 범위와 복잡성 모두에서 확장됩니다. 그 결과, Databricks 엔지니어가 코드를 작성하고 배포하는 모든 환경을 SAFE가 지원할 수 있도록 상당한 투자가 지속적으로 이루어지고 있습니다.
이와 같은 미션 크리티컬 인프라 확장에 관심이 있다면 Databricks의 채용 공고를 살펴보세요!
(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)
