Модернизация legacy-системы крупного речного оператора
Услуги
- legacy-modernization
- complex-systems
- ai-development
Стек
- SvelteKit 2
- Svelte 5
- Supabase Postgres
- Hatchet
- Gotenberg
- PDFKit
- Tailwind 4
Один из крупнейших операторов речных круизов с оборотом десятки тысяч заявок в сезон. Legacy PHP 5.4 + MariaDB монолит за 8+ лет накопил техдолга — невозможно добавлять новые фичи, всё ломается. Задача: миграция на современный стек без потери истории заявок и без downtime.
Контекст
Систему писали разные подрядчики с 2016 года. Накопились классические проблемы:
- PHP 5.4 EOL — невозможно ставить современные библиотеки.
- MariaDB без формальных миграций — изменения схемы делались вручную через phpMyAdmin.
- Бизнес-логика в хранимых процедурах + в шаблонах — отслеживать изменения цен и скидок невозможно.
- Платёжный модуль inline в шаблонах — копипаст между разделами.
- 5 разных способов отправки уведомлений (
mail(), SMTP, telegram-бот, sms-шлюз) без единой шины. - Нет тестов. Релиз = «попробовать в проде, откатить если что».
При этом система обрабатывала тысячи заявок в сезон, и просто переписать всё с нуля означало потерять 8 лет истории заявок, цен, договоров с агентствами.
Подход
Поэтапная миграция с сохранением старой системы в работе и постепенным переключением модулей.
- Migration_app — воспроизводимый pipeline. Extract из MariaDB → Transform (нормализация полей, исправление кодировок, выравнивание типов) → Insert в Supabase PG 17 → Verify (сравнение SQL-выборок legacy ↔ новая БД с диффом). Каждый прогон автоматически детектирует drift и предлагает фикс.
- Public_id 7-символьный для всех URL-сущностей вместо bigint. Backfill через триггеры BEFORE INSERT, без downtime. Короткие URL
/orders/Xy3kR9aвместо/order.php?id=12345. - Insert-only versioning через
valid_from. Единая модель для discounts, prices, booking_rules, promotions, document templates. Старые версии неприкосновенны. Резолвер:max(valid_from) ≤ effective_date. Никаких race conditions при изменении цен. - Universal Document Platform v2 (merged 2026-04-26, tag
pf-pdf-foundation-v1). Hatchet workflows + Gotenberg HTML→PDF + изолированная schemahatchetв общем Supabase Postgres. Заменили самописный PDFKit-pipeline. - Shared modules (shared-pay, shared-notifications, pay-service) для повторного использования между Круизным флотом и параллельным продуктом «Прогулочный флот».
- mTLS + HMAC bridge к остаточной legacy-системе для постепенной миграции — новый фронт ходит к старой PHP за остатками атомарных операций.
Результат
- 211 SQL миграций в production без блокировок (используем
CREATE INDEX CONCURRENTLY,ADD COLUMN ... DEFAULT NULL+ батч-backfill, feature-flags для rollback). - 17 620 единиц данных мигрировано (10 578 круизов + 7 042 прогулок) с побитовой верификацией.
- 312k платёжных записей скорректированы migration drift-fix процедурой за один сеанс (302 940 buh + 9 101 alfabank помечены
site_id='pf'). - 9 LIVE PDF-шаблонов в работе (1 voucher + 1 voucher_pf + 7 версий pf_excursion).
- >1000 одновременных пользователей поддерживается (требование ТЗ).
- 20+ ролей в системе (менеджер, бухгалтер, директор круиза, агент, менеджер агента, физлицо и др.) с разделением через RLS-политики.
- Бизнес-эффект. Время добавления новой фичи: было 1-3 месяца → стало 1-2 недели. Релизы: было редкие и опасные → теперь несколько раз в неделю.
Что использовали
SvelteKit 2 + Svelte 5 runes + Tailwind 4 + shadcn-svelte (frontend), Supabase Postgres 17 + RLS + Edge Functions Deno (backend), Hatchet TS SDK v1 (workflow engine), Gotenberg 8 (HTML→PDF), Альфа-банк SBP C2B + ЮKassa (платежи), mTLS + HMAC + Idempotency (legacy bridge), Caddy auto-TLS, systemd, Docker Compose. AI-усиление: Claude Code SDK + Hermes Stack (9 docker-сервисов) для оперативного контроля проектов.
Похожая задача?
Расскажите контекст — подскажу, что и как делать.
Обсудить похожий проект →