
В июне прошлого года я занимался разработкой проекта для собственных нужд (inventario), где заодно игрался с новыми фичами go, архитектурой кода и агентной разработкой. Благодаря этому проекту, кстати, я смог найти и зарепортить баг с имплементацией дженериков в go.
Изначально простой проект разросся. Росло количество моделей и связей между ними. В какой-то момент я подумал, что неплохо бы озаботиться миграциями для моей системы. Я посмотрел, что имеется в наличии, и мне не зашло ничего. А хотелось мне странного: чтобы модели и были дефиницией моей схемы. Я писал на go, а в go есть паттерн директивных комментариев (//vendor:some:thing без пробела после //). Такие комментарии не имеют какого-то специального значения (за исключением директив компилятору и линкеру), но могут быть обработаны сторонним инструментом (обычно так же написанным на go).
Немного подумав, я завёл новый проект: github.com/stokaro/ptah
Не буду скрывать, проект писался с помощью AI. Однако, если кто-то на этом решил данную страницу, выдохнув: "ууу, очередной ИИ-слоп", то я бы попросил не торопиться с выводами. Дело в том, что да, ИИ может для вас написать код, но инженерные и архитектурные решения ИИ за вас не сделает. Да и различные идеи по ходу разработки тоже не от ИИ исходят. Кроме того любой заинтересовавшийся может посмотреть на активность разработки (на момент написания заметки в основном репозитории было 2414 коммитов, а ещё есть репозиторий с Kubernetes оператором, который достоин отдельной истории). В общем, ИИ можно сильно по-разному использовать.
Изначально я вёл разработку так: сделал что-то в Ptah, пошел применять в Inventario. Нашел баги и пробелы -- повторить итерацию. И так, пока не добился стабильности и безбажности задуманного flow. Но на тот момент Ptah был проект чисто по фану, для собственных нужд. И на какое-то время, после того, как добился нужной мне функциональности и стабильности я его забросил.
Начало разработки
Первый коммит в репозиторий был сделан 3 июня 2025 года (а до этого несколько дней эксперимент жил напрямую в inventario). Всё лето и до начала сентября 2025 инструмент постепенно из эксперимента стал пригладным Go-first экспериментом.
Вот так выглядела примитивная декларация схема на тот момент:
//migrator:schema:table name="users" type User struct { //migrator:schema:field name="id" type="SERIAL" primary="true" ID int64 //migrator:schema:field name="email" type="VARCHAR(255)" not_null="true" unique="true" Email string //migrator:schema:field name="created_at" type="TIMESTAMP" not_null="true" default_fn="NOW()" CreatedAt time.Time }
Однако, я быстро столкнулся с проблемой embedded структур, поэтому парсеру пришлось научиться работать с AST go (stdlib go такой функционал даёт из коробки):
type Base struct { //migrator:schema:field name="created_at" type="TIMESTAMP" not_null="true" CreatedAt time.Time //migrator:schema:field name="updated_at" type="TIMESTAMP" not_null="true" UpdatedAt time.Time } //migrator:schema:table name="users" type User struct { // собственные поля User ... Base }
goschema при обходе User видел embedded Base, и мерджил описание схемы для таблицы users. Поэтому концептуальный результат был:
User ├── ID ├── Email └── Base ├── CreatedAt └── UpdatedAt ↓ flatten users ├── id ├── email ├── created_at └── updated_at
В последствии у Ptah появилась собственная schema-семантика для embedded structures. В более позднем коде появились embedded директивы, обработка embedded FK и всё это было, конечно же, покрыто тестами.
Хочу заметить, что это именно schema definition, а не очередной ORM
На первом этапе получился примерно такой пайплайн для создания и обработки миграций:
Go source ↓ goschema ↓ desired schema ↓ schemadiff ← dbschema ← live DB ↓ planner ↓ AST ↓ renderer ↓ SQL ↓ generator / migrator
Стоит отметить, что изначальная архитектура (frontend → model → diff → plan → render → execute) получилась весьма удачной и дожила с некоторыми изменениями до нынешнего состояния проекта. Более того, я изначально ставил себе целью разрабатывать качественный внешний API-контракт, чтобы библиотеку можно было использовать из go-приложений. В частности, на мой взгляд, AST-слой вышел очень идиоматичным как с точки зрения Go, так и с точки зрения юзабилити.
Стагнация проекта
С середины сентября 2025 года по конец апреля 2026 года наступает длительная пауза в развитии функционала. Лишь изредка прилетают небольшие багфиксы и бампы зависимостей. Всего с 6 сентября 2025 по 30 апреля 2026 года было лишь 24 коммита.
Второе дыхание Ptah
К 7 мая 2026 года функциональная работа плотно возобновляется. PR #118 исправляет молчаливое игнорирование неизвестных атрибутов Go-аннотаций. Конкретный пример: default_fn="NOW()": аннотация могла быть принята, но DEFAULT в SQL не появлялся. Ошибка обнаруживалась уже при применении миграции к непустой таблице. В PR отдельно зафиксирована проверка на реальных моделях Inventario.
Далее появляются и расширения: 17 мая добавляется ClickHouse, 18 мая -- передача context.Context в подключение к БД и ограничение времени подключения. На этой стадии Ptah всё ещё развивается вокруг прежнего движка и Go-аннотаций.
В этот период я уже начал активно думать о том, что я хочу заниматься Ptah больше. Но надо было понять, куда двигаться.
12–21 июля 2026, главный продуктовый перелом: я принял решение взять Atlas как ориентир, с которым мне захотелось добиться feature parity. И хотя кто-то скажет -- Atlas же open source Apache 2.0, бери и форкай, но нет: моей целью была собственная разработка и собственная архитектура, а не клон существующего решения. За всё время работы над Ptah я ни разу не смотрел в их код. 12 июля 2026 года открыт issue #250:
Atlas compatibility: migrate-from vs. native “atlas mode” — decide the strategy.
Это не обычный feature request, а выбор между двумя разными продуктами: помощником для разового перехода с Atlas и инструментом, который способен работать с существующим Atlas-проектом без предварительной полной переделки. Я принял решение сделать совместимость на уровне command-line surface (т.е. заменив бинарь, можно было продолжить пользоваться новым инструментом, не переписывая существующие интеграции).
Претензии со стороны Atlas
Вплоть до 1 августа 2026 года я пользовался исключительно документацией Atlas для имплементации совместимого функционала. В тот день я решил попробовать сделать автоматизированный прогон бинаря ИИ-агентом с целью сбора информации по внешнему контуру -- какие параметры есть, какие ошибки выдаёт и так далее. Но я столкнулся с тем, что бинарь, который устанавливается способом, который указан в официальной документации, требует для некоторого функционала авторизацию на их портале (для CE версии бинарь не дают вообще, насколько мне известно -- мол, собирайте сами). Я зарегистрировался и увидел, что дают триал на месяц. Моё решение было таким - попробую уложиться в месяц, а если не уложусь, возьму на минимальном тарифе.
На следующий день я замечаю, что бинарь более не работает. И агент остановил сбор информации. А в емейле у меня было грозное послание со стороны компании Atlas, мол, прекратите нарушать лицензию (аккаунт мне, конечно же заблокировали).
Как я потом выяснил, Атлас имеет неотключаемую телеметрию, которая собирает неприлично много информации -- они знают о каждом запуске, о локации, где вы запускаете, некоторую информацию о вашем окружении (часть из которой я бы назвал чувствительной). Но это я узнал потом, и является темой для другой статьи.
После пары переписок, я сослался на Articles 5(3) and 8 of Directive 2009/24/EC (а я могу это сделать, потому что я проживаю в ЕС). Но тем не менее я согласился более не прикасаться к проприетарному бинарнику Atlas. На этом конфликт был исчерпан. Я не имею претензий к ним, и они -- я полагаю -- более не имеют претензий ко мне. Сейчас я использую self-built Atlas CE в пайплайнах для автоматизированных тестов паритета и сбора информации о поверхности cli.
Что нас не убивает, ускоряет roadmap.
Инцидент с Atlas меня заставил задуматься сразу о нескольких вещах:
Компания с капиталом посчитала меня -- разработчика-одиночку -- угрозой их бизнесу, что в каком-то смысле является комплиментом.
Я пересмотрел своё отношение к тому, что я использую -- компонентам, инструментам, сервисам. Прежде, чем что-то добавлять в стек, я теперь смотрю, а какие лицензионные правила у данного инструмента.
Я оформил и переписал statement продукта, что я не использую никакие части Atlas, и что разработка ведётся по чешским законам и европейским директивам.
Я тщательно слежу за тем, чтобы ничто в моём проекте не выходило за пределы MIT лицензии, иными словами -- моя цель создать лицензионно-чистый MIT продукт.
"Наезд" со стороны Atlas побудил меня ускориться и более агрессивно имплементировать паритет по функционалу (в т.ч. по pro-features).
Где Ptah сейчас
Если посмотреть на Ptah конца 2025-го года и на то, что получилось сейчас, это уже довольно разные инструменты.
Go-аннотации никуда не делись и по-прежнему являются полноценным способом описания схемы, но Go перестал быть обязательным. Более того, я осознал, что через аннотации невозможно выразить некоторые конструкции, поскольку аннотации пишутся строго в одну строку, и строка может стать неприлично длинной. Плюс включение переносов строк в выражения (хранимые процедуры, функции), становится проблематичной. Поэтому сейчас desired schema может приходить из SQL, YAML, HCL (Atlas-совместимый с Ptah-расширенями), DBML, Go-аннотаций, внешнего loader'а или непосредственно из другой базы данных. Все эти источники сходятся в одну внутреннюю модель, после чего работают одни и те же diff, planner и renderer.
У Ptah сейчас есть два основных workflow.
Первый -- привычные versioned migrations: сравнить desired state с текущей базой, построить diff, проверить потенциально опасные изменения и сгенерировать SQL, который можно коммитить в git вместе с остальным кодом.
Второй -- direct schema management: построить и показать план, а затем привести базу непосредственно к желаемому состоянию. Здесь SQL-файлы миграций вообще не обязаны быть частью контракта.

При этом Ptah уже давно занимается не только CREATE TABLE и ALTER TABLE. Среди поддерживаемых возможностей есть:
PostgreSQL, MySQL/MariaDB, SQLite, SQL Server, ClickHouse и ряд PostgreSQL-compatible СУБД;
declarative schemas из нескольких форматов;
introspection, schema diff и drift detection;
версионированные и direct миграции;
анализ деструктивных изменений и линтинг миграций;
декларативные reference data;
PostgreSQL-специфичные объекты, включая extensions, functions и RLS;
Atlas-совместимые каталоги миграций,
atlas.sum, HCL и часть command-line surface;визуализация и экспорт схемы;
OCI artifacts:
SQL-миграции
Декларативные схемы БД
Результаты линтинга и анализа
Планы миграций
Отчёты о применении миграций (deployment reports)
библиотечный Go API;
отдельный Kubernetes operator;
persistent inference migrations, в том числе управляемая смена поколений embeddings с backfill, verification, cutover и rollback.

Последний пункт стоит особняком и ярко показывает, насколько далеко проект ушёл от первоначальной идеи «прочитать комментарии над Go-структурой и сделать SQL».
При этом Ptah всё ещё pre-GA. Это важно понимать при принятии решений: для продакшн БД я бы не рекомендовал использовать инструмент на данный момент. Если вы это будете делать, то вы действуете на свой страх и риск.
А Atlas-то мы уже превзошли?
Нет.
Atlas существует значительно дольше, имеет команду разработчиков, пользователей, документацию и годы эксплуатации на реальных системах. Утверждать, что небольшой pre-GA проект уже просто «лучше Atlas», было бы как минимум самоуверенно.
Но есть несколько направлений, где Ptah уже получился именно таким, каким я хотел бы его видеть.
Во-первых, у Ptah нет разделения на искусственно урезанный community binary и функциональность, которую локальный инструмент разрешает использовать только после обращения к внешнему сервису. Один open-source продукт, MIT, без каких-либо аккаунтов где-либо (за исключением OCI, но и это лишь ваш выбор).
Во-вторых, compatibility для меня является входом, а не архитектурой продукта. Поэтому Atlas HCL или каталог Atlas migrations -- это такие же источники данных, как SQL, DBML или Go-аннотации. Внутри Ptah они превращаются в собственную модель, а дальше работают обычные механизмы Ptah.
Именно поэтому со временем появился отдельный ptah-compat: совместимость с существующими интеграциями не должна определять архитектуру native CLI.
В-третьих, возможности, которые в других продуктах оказываются коммерческими или облачными, я сознательно хочу оставлять в open-source. Например, declarative reference data для меня не выглядит enterprise-feature: это нормальная часть управления состоянием базы.
Наконец, я стараюсь делать проверяемость частью архитектуры. Для compatibility недостаточно написать в README слово «compatible»: есть conformance tests. Для СУБД недостаточно иметь renderer: есть integration tests и capability matrix. Для Kubernetes operator недостаточно получить успешный exit code из Job: после применения оператор снова наблюдает базу и проверяет convergence.
При этом есть области, где Atlas объективно впереди: зрелость, накопленный production experience, некоторые поддерживаемые объекты и сценарии, документация вокруг edge cases и просто количество реальных пользователей. Именно реальные пользователи сейчас являются для Ptah гораздо более дефицитным ресурсом, чем ещё несколько тысяч строк кода.
Куда дальше
Моя ближайшая цель -- не добавить ещё сто фич ради красивого feature matrix.
Перед GA мне хочется стабилизировать публичные контракты, продолжить закрывать обнаруживаемые conformance gaps, расширять реальные integration-сценарии и, главное, прогонять Ptah не только на придуманных мной fixtures, но и на чужих проектах.
Отдельное направление -- Kubernetes operator. Сейчас это уже самостоятельный control plane с reconciliation, immutable OCI artifacts, approval model и восстановлением после неудачного или неопределённого выполнения. Про его устройство -- если будет спрос -- стоит написать отдельную статью.
Есть и более экспериментальные направления. Одно из них -- persistent inference state: embeddings и другие производные данные тоже приходится мигрировать, только обычной транзакции с ALTER TABLE для этого уже недостаточно. Другое -- AI assistant вокруг Ptah, которому можно дать доступ к структурированной модели схемы, планам и диагностике вместо того, чтобы просить LLM угадывать состояние базы по нескольким SQL-файлам.
Но сейчас мне наиболее критично выяснить, где существующий Ptah ломается в реальных условиях. И где он не решает проблему пользователя.
Поэтому мне нужны люди
Если вы дочитали до этого места и работаете с PostgreSQL, MySQL/MariaDB или просто регулярно имеете дело с миграциями -- попробуйте Ptah.
Мне не обязательно нужны контрибьюторы, готовые сразу писать код. Мне нужны люди, которые возьмут существующий проект и скажут:
«Вот здесь я вообще не понял, что от меня хотят»;
«Вот эту схему Ptah разобрал неправильно»;
«Вот такой migration workflow у нас используется десять лет, а ты его не предусмотрел»;
«Здесь Atlas делает удобнее»;
«Эта команда называется странно»;
«Вот это потенциально снесёт production».
Такая обратная связь сейчас для проекта ценнее ещё одной реализованной мной фичи.
Если же вы хотите поконтрибьютить, я буду только рад. Единственное, что прежде, чем начинать работу над фичой, стоит это обсудить в разделе для дискуссий.
Не хочется заморачиваться с установкой? Не проблема: попробовать Ptah можно даже без установки -- на play.ptah.run работает настоящий Ptah вместе с SQLite, собранные в WebAssembly. Документация и информация по локальной CLI установке находится на docs.ptah.run, исходники -- github.com/stokaro/ptah. Kubernetes operator находится в отдельном репо: github.com/stokaro/ptah-operator.

Буду рад любой конструктивной критике. Если вы убеждены, что вся затея не стоила свеч -- прошу в комментарии, но, пожалуйста, аргументированно :-)

