Ця стаття — не гайд і не туторіал, а чесна розповідь про те, як ми будували платформу даних на open-source і що з цього вийшло. З граблями, компромісами і реальними цифрами.
Коли я прийшов на поточне місце роботи, вся аналітика компанії трималась на Google Таблицях і Looker Studio. Менеджери збирали дані вручну, копіювали цифри з однієї таблички в іншу, і раз на два тижні хтось робив "звіт" — по суті, скріншот з Looker Studio для презентації. Ніхто не розумів, звідки беруться цифри, ніхто не довіряв їм на 100%, і кожен "а чому тут інше число?" перетворювався в годину листування.
Знайомо? Думаю, у 80% українських компаній середнього розміру аналітика виглядає саме так. І це працює — до певного моменту. До речі, деякі результати в нас досі робляться так само — але вже не в тому обсязі, як раніше. Наш момент настав, коли кількість джерел даних виросла, а рішення мали ухвалюватися швидше.
Ця стаття — розповідь про наш шлях від хаосу до Data Lakehouse, чисто на open-source інструментах. Без хмарних провайдерів, без ліцензій за $50k/рік. Зі всіма проблемами, компромісами і висновками.
Початок: Google Таблиці + Looker Studio
Google Таблиці — це ідеальний інструмент для старту. Безкоштовно, зрозуміло для всіх, колаборація в реальному часі. Looker Studio (колишній Data Studio) — безкоштовна BI-система, яка підключається до Google Sheets і показує графіки.
Проблеми почалися, коли:
- Обсяг даних виріс. Google Sheets має ліміт у 10 млн клітинок. Коли у тебе 15+ джерел даних, ти досягаєш цього ліміту швидше, ніж здається.
- Looker Studio гальмував. Дашборди, що тягнуть дані з 5 різних таблиць, завантажуються хвилинами. А якщо хтось зараз редагує вихідну таблицю — взагалі розсипаються.
- Слабке версіонування. Так, Google Sheets має історію змін — але хто реально нею користується? Хтось видалив рядок з таблиці, і ти це помічаєш через тиждень. Шукати, хто і коли це зробив, у стрічці ревізій на 500 змін — окреме задоволення.
- Формули як спагеті. IMPORTRANGE поверх IMPORTRANGE поверх VLOOKUP з іншої таблиці. Одна зміна — і каскад помилок.
Стало зрозуміло: потрібна нормальна інфраструктура даних.
Перша база: MSSQL
Чому MSSQL, а не одразу PostgreSQL? Банально — досвід. На попередній роботі я працював з SQL Server, знав його сильні та слабкі сторони, міг швидко підняти та налаштувати.
До появи нормальної БД вивантаження даних можна було чекати тижнями. Буквально: "можеш дістати ці дані?" — "пиши таск, візьму в роботу". Потім правки, потім ще правки, і так каруселлю. Коли зʼявився MSSQL, час від запиту до відповіді скоротився до годин, а потім — до хвилин.
Тоді ж зʼявився і Airbyte — для переносу даних з інших баз в MSSQL. Працювало це непогано до певного моменту, поки обсяги і кількість джерел не виросли.
MSSQL vs PostgreSQL:
| Критерій | MSSQL | PostgreSQL |
|---|---|---|
| Ліцензія | Express безкоштовно (10 ГБ ліміт), повна — платна | Повністю безкоштовний |
| Екосистема | Windows-центрична, SSMS | Кросплатформенна, pgAdmin, DBeaver |
| JSON-підтримка | Базова | Нативна, JSONB |
| Реплікація | AlwaysOn (Enterprise) | Вбудована, streaming |
| Спільнота | Менша, корпоративна | Величезна, активна |
MSSQL добре працював на старті, але з часом стало зрозуміло, що для нашого випадку PostgreSQL підходить краще — безкоштовний, відкритий, з кращою підтримкою JSON і ширшою екосистемою.
PostgreSQL: робоча конячка
Потім ми підняли PostgreSQL. Зараз туди пише Airbyte, і якщо є потреба в класичних реляційних даних — пишемо теж туди. PG став нашою default базою для структурованих даних.
PostgreSQL vs MySQL:
| Критерій | PostgreSQL | MySQL |
|---|---|---|
| Стандарти SQL | Строге дотримання | Вільне трактування |
| Складні запити | CTE, віконні функції, LATERAL | Базова підтримка CTE |
| Розширюваність | Величезна (PostGIS, pgvector, ...) | Обмежена |
| Реплікація | Logical + physical | Row-based, Group Replication |
| Для аналітики | Добре | Середньо |
MySQL (а точніше MariaDB) теж є в нашому стеку — на ньому працюють продакшн-сервіси компанії. Але для нових аналітичних задач ми завжди обираємо PG.
MongoDB: для специфічних задач
MongoDB зʼявився вже після того, як ми підняли Dremio — під конкретні кейси: парсинг Facebook Graph API, дані із соціальних мереж, де структура відповідей може змінюватися з кожним запитом. Коли API повертає вкладений JSON з довільною глибиною — реляційна БД починає страждати. MongoDB тут почувається як риба у воді.
Оскільки Dremio вже працював, оверхед від ще одного джерела був мінімальний — підключили MongoDB як source, і до всіх баз (MSSQL, PostgreSQL, MongoDB) пишуться однакові SQL-запити через Dremio. Одна мова, один інтерфейс.
MongoDB vs PostgreSQL (JSONB):
| Критерій | MongoDB | PostgreSQL JSONB |
|---|---|---|
| Гнучкість схеми | Повна, schemaless | JSON в реляційних рамках |
| Вкладені документи | Нативно | Потрібні JSONB-оператори |
| Агрегації | Aggregation Pipeline | SQL |
| Масштабування | Sharding з коробки | Citus, партиціювання |
| Для парсингу API | Ідеально | Прийнятно |
Data Lakehouse: чому і що це
Отже, у нас вже було кілька баз: MSSQL, PostgreSQL, MongoDB, плюс дані в Google Sheets, файли, API. Класичний хаос. Кожне джерело — свій формат, свій доступ, свої проблеми.
Data Lakehouse — це архітектура, яка обʼєднує переваги Data Lake (зберігання сирих даних дешево і масштабовано) з Data Warehouse (SQL-запити, ACID-транзакції, схеми). І ми вирішили побудувати його повністю на open-source.
Наш стек:
- MinIO — обʼєктне сховище, сумісне з S3 API. Наш Data Lake
- Apache Iceberg — формат таблиць з підтримкою ACID, time travel, schema evolution
- Nessie — каталог даних з Git-подібним версіонуванням
- Dremio — SQL-движок для запитів до всього цього
MinIO: свій S3
MinIO — це, по суті, self-hosted Amazon S3. Обʼєктне сховище з S3-сумісним API. Все, що вміє працювати з S3 — працює з MinIO.
MinIO vs Amazon S3 vs Azure Blob:
| Критерій | MinIO | Amazon S3 | Azure Blob |
|---|---|---|---|
| Вартість | Безкоштовно (self-hosted) | Pay-per-use | Pay-per-use |
| Контроль | Повний | Обмежений | Обмежений |
| S3 API | Сумісний | Оригінал | Свій API + S3 adaptor |
| Масштабування | Ручне | Автоматичне | Автоматичне |
| Для нас | Ідеально | Дорого для обсягів | Не потрібний |
Для нашого випадку MinIO — ідеальний вибір. Ми контролюємо залізо, немає рахунків за трафік, і все працює так само, як якби ми були на AWS.
Apache Iceberg: таблиці, які не ламаються
Iceberg — це формат таблиць поверх обʼєктного сховища. По суті, він дає тобі можливість працювати з файлами в MinIO так, ніби це таблиці в базі даних. З ACID-транзакціями, з версіонуванням, з еволюцією схеми.
Iceberg vs Delta Lake vs Apache Hudi:
| Критерій | Iceberg | Delta Lake | Hudi |
|---|---|---|---|
| Засновник | Netflix → Apache | Databricks | Uber → Apache |
| Vendor lock-in | Ніякого | Тісно з Databricks | Менший |
| Підтримка движків | Spark, Flink, Dremio, Trino | Spark, Databricks | Spark, Flink |
| Time Travel | Так | Так | Так |
| Schema Evolution | Відмінна | Добра | Добра |
| Партиціювання | Hidden partitioning | Явне | Явне |
| Спільнота | Зростає швидко | Найбільша | Середня |
Iceberg переміг тому, що він найбільш vendor-neutral. Ми не хочемо привʼязуватися до Databricks або будь-кого іншого.
Nessie: Git для даних
Nessie — це каталог даних, який працює як Git. Ти можеш створювати бранчі, робити коміти, мерджити зміни. Для даних. Це звучить як фантастика, але це реально працює.
Nessie vs Hive Metastore vs AWS Glue vs LakeFS:
| Критерій | Nessie | Hive Metastore | AWS Glue | LakeFS |
|---|---|---|---|---|
| Версіонування | Git-like (бранчі, коміти) | Ні | Ні | Git-like (бранчі, коміти) |
| Self-hosted | Так | Так | Ні (AWS only) | Так |
| Iceberg-підтримка | Нативна | Через плагін | Так | Через S3 gateway |
| Складність | Низька | Висока (Hadoop) | Середня | Низька |
| Вартість | Безкоштовно | Безкоштовно | Pay-per-use | Безкоштовно (OSS) |
| Dremio-інтеграція | Вбудована, нативна | Ні | Ні | Ні |
Чому Nessie, а не LakeFS? LakeFS — чудовий інструмент, який версіонує дані на рівні обʼєктного сховища (як Git для файлів в S3). Але Nessie працює на рівні каталогу — він версіонує метадані таблиць, а не самі файли. Для Iceberg-таблиць це ефективніше. А ще Nessie — дефолтний каталог у всіх офіційних туторіалах Dremio. Тобто інтеграція працює з коробки, без танців з бубном.
Nessie — це те, що тримає нашу інфраструктуру разом. Якщо дані в Nessie цілі — все інше можна відновити.
Dremio: SQL-движок, що обʼєднує все
Dremio — серце нашого Lakehouse. Це SQL-движок, який підключається до всіх наших джерел: MinIO через Iceberg/Nessie, PostgreSQL, MSSQL, MongoDB — і дозволяє робити SQL-запити до всього цього як до однієї бази.
Dremio vs Trino vs Apache Spark SQL vs Databricks:
| Критерій | Dremio | Trino (Starburst) | Spark SQL | Databricks |
|---|---|---|---|---|
| UI | Зручний веб-інтерфейс | Мінімальний | Ні | Повноцінний |
| Iceberg-підтримка | Нативна, відмінна | Нативна (відмінна) | Через коннектор | Нативна (Delta) |
| Nessie-інтеграція | Вбудована | Плагін | Плагін | Ні |
| Self-hosted | Community Edition | Так | Так | Ні (SaaS) |
| Оптимізація | Reflections, Columnar Cloud Cache | Кешування | RDD кеш | Photon |
| Простота | Висока | Середня | Низька | Висока |
| Рольова модель | Базова (всі адміни в CE) | Повноцінна | Через Ranger | Повноцінна |
90% наших таблиць в Dremio — це view. Ми свідомо мінімізуємо копіювання даних. Замість того, щоб дублювати дані в окремі таблиці, ми створюємо view поверх джерел, а для прискорення — додаємо Reflections (матеріалізовані агрегати, які Dremio створює і оновлює автоматично). Це дозволяє тримати мінімум фізичних копій: агреговані дані зберігаються як Reflections, неагреговані — як view з іншим представленням. Запити до view виконуються швидко за рахунок Reflections, а дані завжди актуальні, бо view читають напряму з джерела.
Головна проблема Dremio Community Edition — і це стосується багатьох OSS-продуктів — відсутність нормального керування ролями. В Community Edition всі користувачі — адміни. Ти не можеш обмежити доступ до певних датасетів або дати read-only права. Для маленької команди це терпимо, але з ростом — болить.
Поки що доступ до Dremio в нас тримається на довірі — команда невелика, всі розуміють, куди можна лізти, а куди ні. Частково ми вирішили цю проблему через MCP-шлюз, про який розкажу нижче — він додає ACL-шар поверх Dremio і контролює, хто до чого має доступ. Але для прямих підключень до Dremio проблема залишається — це один із тих компромісів, з якими живеш в OSS: функціонал є, але access control — добудовуй сам.
Це, до речі, типова проблема OSS: безкоштовна версія дає 80% функціональності, але той критичний 20% (security, RBAC, audit log) — в платній версії. І ти або платиш, або живеш з компромісами — або будуєш обхідні рішення.
Кейс: оновлення Dremio, що пішло не так
Одного дня ми вирішили оновити Dremio до нової версії. Dremio у нас крутиться в Docker Compose, тому процес мав бути простим: змінити тег образу, docker compose up -d, готово. Але щось пішло не так — після запуску Dremio не бачив половину датасетів. Внутрішні метадані зіпсувались при міграції. В логах — стіна помилок без нормального опису проблеми. Що саме зламалось — незрозуміло. Ми витратили час на дебаг, але врешті вирішили знести все з нуля і підняти чисту інсталяцію.
Момент паніки? Так, секунд на тридцять. А потім — "стоп, у нас же Nessie". Всі наші Iceberg-таблиці, їхня схема, історія змін — все зберігається в Nessie, а не в Dremio. Dremio — це лише движок для запитів. Ми підняли чистий Dremio, перепідключили Nessie-каталог, і всі дані повернулись. А всі view у нас були описані в dbt — одна команда dbt run, і всі view розгорнулись назад. За годину все працювало як раніше.
Це був момент, коли архітектурне рішення розділити compute (Dremio) і catalog (Nessie) виправдало себе на 200%. Якби ми покладалися на внутрішній каталог Dremio — відновлення зайняло б дні, а не годину.
Кейс: DELETE без WHERE, або як Nessie врятував за 2 секунди
Є класичний жарт про DELETE FROM table без WHERE. Так от, у нас це був не жарт.
Одного разу я запустив DELETE-запит на Iceberg-таблицю і забув додати умову. Просто DELETE FROM ... — і все. Таблиця очистилась миттєво. Серце зупинилось на секунду, руки похололи — там були дані, які збирались тижнями.
Якби це була звичайна PostgreSQL або MSSQL — це був би кінець. Бекап? Може, вчорашній. А дані за сьогодні — втрачені. В кращому випадку — години на відновлення з бекапу, перевірку цілісності, ручне доливання свіжих даних.
Але у нас Nessie. А Nessie — це Git для даних. Кожна зміна — це коміт. Кожний коміт має хеш. Я просто відкатив бранч до попереднього коміту — і через 2 секунди всі дані були на місці. Як ніби нічого не сталось.
Два. Секунди.
До речі, таке ж саме траплялось і з MSSQL — DELETE без WHERE на продакшн-таблиці. Тільки там Nessie не було. Бекапу свіжого — теж. Довелось відновлювати все з нуля: піднімати старий бекап, порівнювати з продакшном, вручну доливати дані, які встигли накопичитись. Це зайняло не секунди, а години. І нервів — на місяць вперед.
Це той момент, коли розумієш, чому time travel і версіонування даних — це не маркетингові слова, а реальна страховка від людських помилок. Ми всі робимо помилки. Питання лише в тому, скільки часу потрібно на відновлення. З Nessie відповідь — секунди. З MSSQL — години і сіде волосся.
Airbyte: інгест даних
Airbyte — наш інструмент для витягування даних з різних джерел. Зараз він тягає таблички з Google Sheets і пише в PostgreSQL. Інколи використовуємо no-code connector builder — коли впадло писати asset в Dagster, а потрібно швидко підключити нове джерело.
Airbyte OSS vs Fivetran vs Meltano vs dlt:
| Критерій | Airbyte OSS | Fivetran | Meltano | dlt |
|---|---|---|---|---|
| Ліцензія | Open-source | SaaS, платний | Open-source | Open-source |
| Кількість конекторів | 300+ | 400+ | 300+ (Singer) | Бібліотека |
| UI | Веб-інтерфейс | Веб-інтерфейс | CLI | Код |
| No-code builder | Так | Ні | Ні | Ні |
| Self-hosted | Так | Ні | Так | Так (це бібліотека) |
Проблеми Airbyte OSS, які ми зустріли:
- Ресурсоємність. Зараз Airbyte віджирає 12 ГБ оперативки і толком нічого не робить. Плануємо його дропнути. Він складно справляється з великими обсягами даних — синхронізація може виконуватись днями, і при цьому жодної помилки не буде. Просто тихо молотить.
- Нестабільність конекторів. Деякі community-конектори ламаються після оновлень. Синхронізація з Google Sheets час від часу падає без видимої причини і потрібно перезапускати.
- Складний дебаг. Коли щось падає — логи розкидані по десятку Docker-контейнерів. Знайти, що саме пішло не так, іноді займає більше часу, ніж сам фікс.
- Оновлення. Кожне оновлення Airbyte — це лотерея. Може пройти гладко, а може зламати конектори, які працювали місяцями.
Але при цьому Airbyte все одно кращий варіант для нас, бо Fivetran коштує стільки, що дешевше найняти ще одного дата-інженера.
Dagster: оркестрація
Dagster — наш оркестратор. Він визначає, що, коли і в якому порядку запускається. Кожен pipeline — це набір assets, які Dagster відстежує, запускає за розкладом або за тригером.
Dagster vs Apache Airflow vs Prefect vs Mage:
| Критерій | Dagster | Airflow | Prefect | Mage |
|---|---|---|---|---|
| Концепція | Software-defined assets | DAGs of tasks | Flows & tasks | Blocks & pipelines |
| UI | Сучасний, зручний | Функціональний, застарілий | Хмарний | Notebook-style |
| Тестування | Вбудоване | Складне | Середнє | Базове |
| Типізація | Сильна (IO managers, types) | Слабка | Середня | Слабка |
| dbt-інтеграція | Нативна (dagster-dbt) | Через оператори | Через блоки | Базова |
| Складність | Середня | Висока | Низька | Низька |
Чому Dagster, а не Airflow? Тому що Airflow — це 2015 рік. DAGs, operators, XCom — це все працює, але відчувається як legacy. Dagster побудований навколо концепції assets — ти описуєш не "що запустити", а "які дані потрібно отримати". Це фундаментально змінює підхід.
Окремо хочу відзначити в Dagster механізм dependency injection — дуже крутий і дуже зрозумілий. Чомусь згадуються студентські роки і Dagger 2 під Android, де все було максимально заплутано. Тут — відразу все ясно, все на місці.
Ще один плюс Dagster — нативна підтримка запуску Airbyte, Airflow та інших інструментів. Тобто якщо потрібно мігрувати з іншого оркестратора або інтегрувати зовнішній тул — це робиться на ізі, без милиць.
dbt: трансформація
dbt — це трансформації. SQL-моделі, які перетворюють сирі дані в аналітичні таблиці. dbt працює з Dremio через адаптер, і це дозволяє нам будувати моделі поверх Iceberg-таблиць.
Важливий нюанс: зараз Dagster і dbt у нас не зʼєднані. dbt запускається при пуші через GitLab CI/CD pipeline — оновив SQL-модель, зробив push, GitLab запускає dbt run проти Dremio. Це працює, і нагальної потреби інтегрувати dbt в Dagster поки немає. Але плануємо — це логічний наступний крок, щоб мати єдину точку оркестрації.
На сьогодні наш dbt-проєкт — це 445 моделей, 848 тестів, 103 sources і 652 макроси. Це не просто SQL-файли — це повноцінна кодова база з версіонуванням, code review і CI/CD.
Окремий бонус: dbt генерує документацію, яку ми заливаємо в Dremio wiki з лінком на dbt docs.
MCP-шлюз: AI-клієнт для Dremio
Одна з найцікавіших речей у нашому стеку — MCP-сервер (Model Context Protocol), підключений до Dremio. По суті, це шлюз, через який AI-асистенти (Claude, Cursor, будь-який MCP-клієнт) можуть ходити в наш Lakehouse — робити SQL-запити, читати метадані таблиць, переглядати dbt-документацію.
Але головна фішка не в цьому. Головна фішка — контроль доступу. Як я вже писав, Dremio Community Edition не має нормальної рольової моделі — всі користувачі по суті адміни. MCP-шлюз вирішує цю проблему: він має власний ACL-шар, який контролює, хто до яких датасетів має доступ. Кожен запит від AI-клієнта проходить через перевірку прав — і якщо у тебе немає доступу до певного простору або таблиці, ти його просто не побачиш.
Тобто те, чого немає в самому Dremio, ми добудували на рівні шлюзу. Це дозволяє безпечно давати доступ до даних різним людям і AI-агентам — кожен бачить тільки те, що йому дозволено.
dbt vs Dataform vs SQLMesh:
| Критерій | dbt | Dataform | SQLMesh |
|---|---|---|---|
| Спільнота | Величезна | Менша (Google) | Зростає |
| Адаптери | 30+ | BigQuery-центричний | 10+ |
| Версіонування | Git | Git | Git + автоматичне |
| Тестування | Вбудоване | Вбудоване | Розширене |
| Incremental | Стандартне | Стандартне | Просунуте |
| Ціна | Core безкоштовний | Безкоштовний (GCP) | Безкоштовний |
Apache Superset: BI для всіх
Looker Studio замінили на Apache Superset. Це BI-платформа, створена в Airbnb і передана в Apache Software Foundation. Підключається до будь-якої SQL-бази — включаючи Dremio.
Superset vs Metabase vs Looker Studio vs Grafana:
| Критерій | Superset | Metabase | Looker Studio | Grafana |
|---|---|---|---|---|
| Ліцензія | Apache 2.0 | AGPL / Commercial | Безкоштовний (Google) | AGPL |
| SQL Lab | Повноцінний | Є, спрощений | Ні | Explore |
| Візуалізації | 50+ типів | 15+ | 30+ | Для метрик |
| Self-hosted | Так | Так | Ні | Так |
| Кастомізація | Висока | Середня | Низька | Висока |
| Рольова модель | Повна (RBAC) | Базова | Google accounts | Org/Team |
| Для аналітики | Ідеально | Добре | Базово | Для моніторингу |
Superset муторно налаштовувати — первинний setup це окремий квест, UI іноді глючить, деякі графіки потребують танців з бубном, а документація... скажемо так, вона існує. Але коли все налаштовано — він класний. Для безкоштовного продукту — це найкращий варіант BI, який ми знайшли.
Проблема OSS: де закінчується "безкоштовно"
Найбільший міф про open-source — "це безкоштовно". Так, ліцензії безкоштовні. Але:
- Час на налаштування. Кожен інструмент потрібно підняти, налаштувати, зінтегрувати. Це тижні роботи.
- Відсутність підтримки. Коли щось ламається — ти сам. GitHub Issues, Stack Overflow, Discord — і молися, щоб хтось відповів.
- Рольова модель. Як я вже казав, в Dremio CE всі — адміни. В Airbyte OSS теж не густо з правами. В Superset є нормальний RBAC, але налаштувати його — окремий квест.
- Оновлення. Кожне оновлення кожного компонента — це потенційний breaking change. І ніхто тобі не гарантує, що нова мажорна версія Airbyte буде сумісна з твоїм конфігом — ми це відчули на собі при переході на 2.0.
Але при цьому — ми повністю контролюємо свою інфраструктуру. Ніякого vendor lock-in. Ніяких несподіваних рахунків від AWS. І найважливіше — ми розуміємо кожен компонент системи, бо самі його налаштовували.
Висновки
Наш шлях від Google Sheets до Data Lakehouse зайняв десь два роки. Не тому що це складно зробити за раз — а тому що кожен інструмент підключався по мірі виникнення проблем і потреб. Це був органічний процес з помилками, відкатами, і "а давай спробуємо ось це". Але зараз у нас є:
- Єдина точка доступу до даних — Dremio, де всі джерела обʼєднані
- Версіонування даних — Nessie, де кожна зміна відстежується
- Надійне сховище — MinIO + Iceberg, де дані зберігаються в відкритому форматі
- Автоматизація — Dagster для оркестрації, dbt для трансформацій через GitLab CI/CD
- BI для всіх — Superset, де менеджери самі будують дашборди
Чи ідеальна ця система? Ні. Є проблеми з ролями, є баги в OSS-продуктах, є моменти, коли хочеться просто заплатити за SaaS і не думати. Але для нашого масштабу і бюджету — це найкращий варіант, який ми змогли побудувати.
І головний висновок: дані — це не про інструменти, а про процеси. Найкрутіший стек не допоможе, якщо люди не розуміють, навіщо він потрібний. Ми почали з простого — показали, як швидше отримувати відповіді на питання. Решта прийшла сама.