
Несколько лет назад наш корпоративный слой данных жил на проприетарных технологиях. Данных было много, а основная СУБД — MPP-система Sybase IQ — долго не обновлялась. Мы регулярно сталкивались с тем, что у кластера «падали» ноды, каталог базы повреждался, порой даже терялись данные, а вендор не спешил выпускать исправления или даже признавать проблему. ETL-процессы работали через IBM DataStage, который также перестал развиваться. Все решения были закрыты, и мы не могли влиять на их улучшение. Vendor lock-in означает, что вы зависите от поставщика: если вендор не поддерживает нужные возможности, развитие замедляется, а долгоживущие ошибки остаются нерешенными. Такое положение становилось критичным.
Мы поняли, что для устойчивого развития платформы нужно срочно искать альтернативу: переходить на стек, которым мы можем управлять сами. При этом важно было сохранить команду: десятки разработчиков и аналитиков уже работали с существующей моделью. Новому решению следовало быть удобным для аналитиков, прозрачным для бизнеса и гибким для инженеров.
В этой статье расскажу о том, как мы перешли с проприетарных ETL-инструментов на open-source на базе dbt, какие проблемы решали по ходу внедрения, и как построили экосистему вокруг dbt для автоматизации рутинных задач.
Зачем вообще менять?

Со старой платформой у нас было несколько проблем:
Зависимость от вендора. Проприетарные базы и ETL — это дорого. Мы столкнулись с классическим vendor lock-in: лицензии и сопровождение стоили миллионы рублей в год, а развитие тормозилось из-за негибкости поставщика.
Устаревшие технологии и нестабильность. Sybase IQ и DataStage давно не получали существенных обновлений. Их процессами сложно было управлять, интеграция с современными СУБД (Greenplum, ClickHouse, Impala) требовала постоянных костылей. Все это сопровождалось периодическими «падениями» базы, а иногда даже потерей данных. Отдельные разработчики тратили больше времени на стабилизацию работы, чем на построение витрин.
Сложные процессы. ETL строился на асинхронных вызовах и семафорах, что было сложно сопровождать; в тестовых средах возникали конфликты, а изменения схемы приходилось делать вручную. Настроить CI/CD и автоматические тесты для такой архитектуры было почти невозможно.
И наконец, бизнес хотел не просто стабильную систему, а платформу, где новые витрины строятся быстро и понятно, где можно легко проследить происхождение данных и где нет черных ящиков.
Кроме того open-source-продукты позволяют свободно использовать, модифицировать и распространять код, что делает такие решения гибкими и экономически эффективными.
Как выбрать новый инструментарий
Когда мы решили уходить от проприетарной платформы, нужно было подобрать два ключевых компонента: средство трансформации и средство оркестрации.
До миграции наша банковская платформа уже имела несколько open-source-MPP-движков: Greenplum, Apache Impala, Apache Spark. Однако ни один из них не решал задачу «запускайте один и тот же бизнес-SELECT в разных СУБД» — это просто СУБД или вычислительные движки, а не инструменты описания и контроля трансформаций.
Мы не хотели привязываться к конкретной базе: в каких-то проектах удобен Greenplum, в других — Impala или ClickHouse, а завтра может появиться что-то еще. Поэтому важным требованием стало наличие инструмента, который генерирует SQL-код независимо от конкретной СУБД и тем самым позволяет описывать трансформации один раз, выполняя их на любой поддерживаемой базе.
Трансформация
На рынке множество решений, но большинство из них либо требуют глубоких инженерных навыков, либо жестко привязаны к конкретным стекам:
Apache Spark — популярный движок обработки больших данных, который предоставляет несколько способов описания преобразований. Благодаря наличию модуля Spark SQL он подходит аналитикам, которые могут работать с ним будто с обычной СУБД, с помощью привычных SQL-запросов. Однако Spark сам по себе не концентрирует внимание на бизнес-логике, не помогает описывать модели единым и однозначным путем и собирать их воедино в структурированный проект.
Talend, Pentaho и другие классические ETL-платформы. Это мощные визуальные инструменты, но они дорогие и закрытые. Легаси-решения вроде Talend и Informatica плохо подходят к современным требованиям: они не работают с неструктурированными данными, требуют дорогостоящих лицензий и мощных серверов, а отсутствие автоматизации заставляет команды тратить 80% времени на ручное сопровождение и устранение ошибок.
Dataform (Google) — управляется Google и тесно интегрирован с BigQuery, который работает в облаке и не «приземлен» в России. К сожалению, в нашем случае облачные решения неприменимы.
По совокупности критериев мы выбрали dbt (есть еще его прямой конкурент — SqlMesh, и, возможно, мы присмотримся к нему в будущем, но на момент нашего старта он был сыроват). dbt позволяет аналитикам описывать сложную логику на привычном SQL, что снижает порог входа. Но главное — dbt обеспечивает независимость от СУБД: он генерирует код под конкретную базу (Greenplum, ClickHouse и т. д.), решая проблему с мультиплатформенностью.
Инструмент предоставляет встроенные возможности для тестирования, документирования и версионирования кода трансформаций. При этом функциональность можно расширять через макросы и пакеты, не трогая основной код инструмента. И наконец, вокруг dbt сложилась богатая экосистема с большим количеством полезных библиотек от сообщества (например, dbt-utils, dbt-expectations), которые заметно ускоряют разработку и закрывают типовые задачи.
Оркестрация
Для управления процессами трансформации нужен оркестратор. Вот что мы рассматривали:
Prefect, Dagster — относительно новые инструменты с упором на Python и динамические пайплайны. Они предлагают современные подходы и удобный developer experience, но на момент нашего выбора их экосистема была небольшой, а интеграции с dbt не так хорошо отработаны.
Luigi — оркестратор от Spotify, но он уже устарел и имеет ограниченную функциональность по сравнению с более современными решениями.
Airflow — самый «зрелый». Его поддерживает Apache Software Foundation, у него огромное сообщество с готовыми решениями типовых задач и проверенные интеграции с dbt.
Выбор пал на Airflow. Он надежный, определение пайплайнов в виде кода на Python (DAGs) дает полный контроль над логикой и зависимостями, а готовые интеграции, включая нативную поддержку для запуска задач dbt, позволяют быстро запустить процесс. В итоге связка dbt + Airflow обеспечила нам свободу выбора технологий, SQL-подход для аналитиков и мощную экосистему для дальнейшего развития.
Что не так с «ванильным» dbt

Хотя dbt — действительно мощный инструмент, для построения DWH в реальном enterprise-проекте многое хочется кастомизировать, чтобы работало немного иначе.
Работа со схемой. Из коробки dbt incremental не имеет backfill. Добавление колонки в инкрементальную модель обычно приводит к полной перезагрузке таблицы. Это неприемлемо для таблиц на десятки терабайт. Также хорошо бы типы колонок и constraints протягивать «как их запроектировали» для дальнейших автоматических контролей. На тот момент dbt такого не поддерживал. Кроме того, есть особенности применения изменений в различных СУБД, которые хотелось обыграть отдельно.
Поддержка различных СУБД. В нашем же стеке есть Greenplum с партиционированием, ClickHouse с шардированием и ReplicatedMergeTree, Impala и Spark с файлами iceberg в S3. Адаптеры не всегда актуальны и поддерживают современные версии СУБД и их особенности для оптимальной работы.
Контроль доступа. В dbt нам не хватило кроссплатформенного ролевого механизма разграничения прав на уровне моделей и схем. Настраиваться все должно простым назначением роли.
Рутинные действия. Разработчики вынуждены тратить непропорционально много времени на инфраструктурную рутину вместо бизнес-логики. Для каждой модели пишется инкрементальная загрузка, поддерживается историчность (SCD 2–4), генерируются суррогатные ключи. В результате фокус внимания смещается с бизнес-ценности на техническую обвязку. К тому же такой зоопарк тяжело поддерживать. Нужно бы стандартизировать.
Оркестрация и масштабирование. Граф из тысяч моделей превращается в спагетти. При стандартном подходе DAG Airflow отображает все модели одним длинным списком. Компиляция большого проекта занимает минуты и даже часы. Пришлось решить, как правильно разделять и оркестрировать проекты.
Штатные материализации. Для каждой СУБД есть свои особенности применения изменений update / insert / merge / insert overwrite. Хотелось написать модели так, чтобы не переписывать их под каждую версию СУБД. И чтобы можно было подкрутить настройки своей материализации, не трогая бизнес-код, в случае, когда найдется более оптимальный подход.
Проверки типов. Есть требование гораздо более гибко проверять и контролировать типы данных, constraints, дубли и т. д. В нашем случае нужны поколоночные настройки поведения, возможная корректировка данных, ведение журнала ошибок для последующего разбора.
Что мы сделали: экосистема вокруг DBT
Мы решили, что dbt core — это ядро, и не стали форкать или модифицировать его. Теперь можно безболезненно обновляться и пользоваться всеми библиотеками и плагинами, которые развивает сообщество. Весь дополнительный функционал реализован поверх dbt — через макросы, материализации и самописные Python-утилиты. Поверх ядра построили целую экосистему, которая автоматизирует рутинные задачи.
Кастомные материализации и макросы
Главная идея — превратить тяжелый ETL-код в low-code: разработчик пишет лишь бизнес-SELECT, а весь «служебный» код делает материалиация. Это позволяет аналитику или дата-инженеру сосредоточиться на смысле данных, а не на инфраструктуре.
Наши материализации берут на себя всю техническую рутину:
Автоматическое управление схемой. Мы реализовали функционал, который анализирует различие между метаданными модели (schema.yml) и базой, выбирает стратегию (добавить колонку и заполнить ее в пайплайне, выдать ошибку несоответствия метаданных, пересоздать таблицу по метаданным) и выполняет необходимый DDL при заданных заранее условиях и настройках в пайплайне CI/CD, — ровно то же делал разработчик при тестировании функционала. Т. к. DDL полностью генерируется автоматом — исключен человеческий фактор. Если же по каким-то причинам база поменяется, а модель нет, — Dag загрузки модели будет падать с ошибкой, не позволив испортить данные.
Low-code. Разработчик пишет только SELECT, а функционал сам формирует набор ключевых полей для инкрементальной загрузки, поддерживает разные стратегии инкремента и позволяет вести историю по модели SCD 4. Так же генерятся суррогаты, пишутся логи, инкремент режется на батчи, автоматически поддерживаются техполя. И все это стандартизировано для 2000+ моделей.
Встроенный контроль качества. Проверка на дубли, контроль ссылочной целостности (foreign keys) и приведение типов выполняются автоматически. Для каждой строки формируется «тракт» данных — идентификатор, по которому можно отследить ее до источника или приемника.
Мультиплатформенность. Одна и та же модель работает под Greenplum, ClickHouse и Spark благодаря адаптивной генерации SQL.
Объектные права и безопасность. Материализация создает таблицы и представления с корректными привилегиями для ролей разработчиков, аналитиков, сервисов и прочих.
Инкрементальная репликация в ClickHouse. dbt может выгружать готовые витрины через EXTERNAL TABLE и автоматически инкрементально реплицировать их в ClickHouse без ручного кода.
Мониторинг. Мы ведем метабазу запусков потабличных загрузок. В Grafana доступна вся информация о data-freshness, SLA, времени готовности витрин, ошибках при их формировании, техническом качестве данных. Все группируется по тегам моделей, давая возможность проверить готовность тех или иных витрин данных, системы-источника и т. д.
Специфические настройки для баз. Для GreenPlum автоматически поддерживаем партиции, для Impala — хинты, разные типы файлов, merge / insert overwrite и еще множество кастомизаций.
Оркестратор и генератор DAG’ов
Чтобы не писать DAG'и для Airflow вручную (при большом количестве моделей это довольно больно), мы разработали утилиту DagGenerator. В описании модели в schema.yml архитектор задает теги (например, source_system:CRM, domain:Loans) — эти теги определяют, в какой DAG попадет модель.
DagGenerator читает настройки из YAML-файла и создает DAG'и с расписанием и зависимостями, отбирая модели по тегам. Добавление новой модели в DAG происходит динамически, по тегу. Это исключает ошибки из-за человеческого фактора и упрощает поддержку. Кроме того, мы добавили в утилиту функционал построения зависимостей не только по ref-ссылкам, но и по внешним ключам моделей, описанных в их метаданных.
Утилиты и инструменты
Metadata Manager. Это универсальная утилита чтения и записи метаданных. Она подключается к любой СУБД, считывает структуру таблиц (колонки, типы, PK, FK) и формирует из этого schema.yaml для dbt. Развертывание проекта на «чистой» базе сводится к запуску dbt.
Утилита для выгрузки YAML. Архитектор проектирует модель в CASE-инструменте, нажимает кнопку — генерируются schema.yaml. Скрипт выгружает структуру модели, избавляя от ручного копирования.
Генератор шаблонных моделей. Отдельная утилита, которая создает простые dbt-модели и YAML-описания по шаблону. Ускоряет создание однотипных витрин и стандартизирует их структуру.
Мониторинг и метрики. Логи выполнения сохраняются в ClickHouse, а дашборды строятся в Grafana. Мы видим, сколько времени работала каждая модель и каждый ее шаг, сколько записей прошло / не прошло проверки и где произошел сбой. Также мы контролируем SLA витрин и систем.
Интеграция с data lineage. Manifest и SQL-код автоматически отправляются в Open Metadata; таким образом мы получаем колоночный lineage и всю структуру нашей базы с описаниями и прототипами.
Расширения
Мы старались использовать лучшее, что предлагает сообщество, и дополнили наш стек следующими решениями:
dbt-utils. Фундаментальный набор макросов и тестов (генераторы SQL, surrogate_key, универсальные тесты).
dbt-expectations. Библиотека тестов, вдохновленная Great Expectations, для богатых проверок данных (типы, диапазоны, количество колонок) в формате YAML.
dbt-external-tables. Пакет для декларативного описания внешних таблиц (например, файлов в S3 или HDFS) прямо в dbt.
Elementary. Расширение, которое отправляет отчеты о тестах в Slack или почтой и автоматически формирует отчеты о качестве данных.
Astronomer Cosmos. Библиотека, упрощающая интеграцию dbt и Airflow. Она разбивает большую задачу на несколько TaskGroup и улучшает визуализацию.
Плагины для IDE. Расширения для VS Code и JetBrains DataSpell, которые подсвечивают макросы dbt и позволяют запускать модели прямо из редактора.
Процесс и роли
Технологии — только половина успеха. Мы детально прописали процесс разработки и роли в нем.
Аналитик: собирает требования, пишет прототип на SQL и оформляет бизнес-описание.
Архитектор: проектирует модель в CASE-инструменте и выгружает YAML-описание.
Разработчик: на основе прототипа и YAML пишет конечную модель в dbt. Ему не нужно думать об инкрементах — все делает материализация.
Тестировщик + Аналитик: проверяют модель и пишут тесты (разовые для проверки доработки или регрессионные для постоянного запуска по модели в случае изменений).
Dev-ops. CI/CD-конвейер: запускает пайплайн. Решение конфликтов, компиляция dbt, запуск тестов и линтеров для SQL и YAML. После этого — генерация документации, обновление DAG’ов и деплой.
Поддержка. Продакшен — финальный шаг. Новая модель попадает в прод, а мониторинг (Grafana + Prometheus) наблюдает за ее работой вместе с коллегами из технической поддержки.
Благодаря такому процессу у каждой активности есть владелец, прозрачные точки контроля и автоматические проверки.
Что на выходе
Благодаря шаблонизации, low-code-разработке, автотестам и автоматическому управлению схемой (DDL) количество ошибок сократилось примерно вдвое. Настолько же увеличилась скорость внедрения доработок: разработчики теперь фокусируются на бизнес-логике, а не на технической рутине.
Покрытие тестами выросло до 85%, ошибки перехватываются еще в процессе CI/CD, не доходя до прода.
Платформа легко масштабируется: сейчас в репозитории более 2000 моделей, а в команде работает более 50 разработчиков. Персональные песочницы и динамические DAG'и позволяют им работать параллельно без конфликтов.
Экономический эффект: стоимость лицензий на проприетарные продукты сократилась в разы. Переход на open-source дал возможность развивать платформу самостоятельно, не завися от roadmap-вендора.
Наконец, платформа стала прозрачной для бизнеса. Благодаря встроенной документации dbt и интеграции с Open Metadata мы можем показать бизнес-пользователям путь каждого показателя в витрине данных, сообщить время его выгрузки из источника (data-freshness) или спрогнозировать время загрузки.
Заключение
Если вы задумываетесь о миграции с проприетарных систем, присмотритесь к dbt. Сообщество активно развивается и предлагает готовые пакеты, которые можно использовать в существующем виде или расширять под свои задачи. Менять привычный стек непросто, но open-source дает возможность строить систему, которая работает именно так, как нужно вам, а не так, как решил вендор.