Case Study | 20.03.2026 Shoptet Pay — Team Lead

Engineering
Team Lead

Jak vést databázovou refaktorizaci, aniž bychom zastavili produkt (a proč to není jen technický problém)

Nikolai Baranov
[email protected] | +420 777 611 516
Pozice
Shoptet Pay Team Lead
O mně

Kdo jsem & proč tohle zadání

photo_2026-03-08_19-07-09.jpg
Nikolai Baranov
CTO @ Proof & Reason
13+ let v IT. Začínal jako Fullstack developer (PHP/Symfony, React/Next.js), přes DevOps a Tech Lead až na CTO. Vedu tým 12 vývojářů, zajišťuji aby technická řešení přinášela byznysovou hodnotu.
Fullstack PHP / Symfony Next.js / React DevOps Tech Leadership
13+

Let v IT

Od C++ a Xamarin po CTO. Fullstack vývoj stále jako priorita.

12

Vývojářů v týmu

Vedení přes heady, denní problémy, strategická rozhodnutí.

01

Proč Shoptet Pay

Chci propojit technologie s reálným dopadem na lidi a produkt. Shoptet Pay beru jako novou, ambiciózní výzvu, která mě posouvá dál.

01 / Výzva

Nejdřív to, co nevím

Než navrhnu cokoliv konkrétního, musím říct jednu věc na rovinu: nevím, na čem aplikace běží. A není to detail.

V inzerátu se zmiňuje MariaDB. Pokud je to pravda, část technického přemýšlení, které by platilo pro PostgreSQL, tady prostě neplatí.
  • MariaDB (Galera Cluster) — DDL operace koordinuje jinak. ALTER TABLE je ve výchozím stavu blokující přes celý cluster (TOI mode).
  • Nástroje — pt-online-schema-change nebo gh-ost fungují s MariaDB, ale mají svá specifika. Konkrétní otázka na první call.
  • Archivační pipeline — musí respektovat cluster sémantiku, jinak riskujeme split-brain nebo nekonzistentní stav.
Každé níže popsané řešení beru jako konceptuální rámec. Konkrétní implementace závisí na odpovědi na tuhle otázku.
? MariaDB Postgres? zjistit v Fázi 0
02 / Problém

Problém není objem dat

Zadání popisuje symptomy. Kořen problému je jiný — a špatně definovaný problém vede ke špatně zvolenému řešení.

Máme jednu tabulku, která obsluhuje dva fundamentálně odlišné případy použití: aktivní data (mění se spolu s produktem) a historická data (mrtvá, přistupuje se k nim zřídka).
  • Tyto dva světy mají odlišný životní cyklus, odlišnou frekvenci přístupu a odlišnou potřebu flexibility.
  • Každá změna schématu — která se týká jen aktivních dat — musí projet přes miliony historických řádků, které s tou změnou nemají nic společného.
Neřešíme "jak zvládnout velký objem dat". Řešíme jak oddělit životní cykly dat tak, aby vývoj produktu mohl jít rychle.
SHARED TABLE (problém) AKTIVNÍ mění se HISTORICKÁ zmrazená každý ALTER TABLE prochází oběma
03 / Přístupy

Tři konceptuální přístupy

Před výběrem technologií musím pochopit, že existují tři různé konceptuální přístupy. Každý má jiné důsledky pro kód, provoz i tým.

A

Zlevnit migrace (tooling)

Necháme data tam, kde jsou, ale používáme nástroje (pt-osc, gh-ost) pro online schema migrations bez dlouhého locku. Kód se nemění — problém růstu dat ale zůstává, jen ho oddálíme.

B

Archivační vzor

Přesuneme historická data do jiného úložiště. Hlavní DB zůstane malá. Kód musí vědět, kde hledat — potřebuje dvě připojení, dvě repository vrstvy, nebo smart routing.

C

Legacy layer přístup

Definujeme čáru v písku. Historická data jsou zmrazena, přistupuje se k nim přes dedikovanou read-only vrstvu v kódu. Archivní DB nikdy nedostane schema migration. Nový kód pracuje jen s aktivními daty.

Volba přístupu závisí na odpovědích z Fáze 0 — zejména na tom, zda historická data vstupují do aktivního rozhodování (scoring, ML).
04 / Dopad na kód

Co to znamená pro kód aplikace

Tohle je podle mě nejdůležitější část — a v diskusích o databázovém škálování se na ni zapomíná. Technologické rozhodnutí je sekundární.

  • Dvě DB připojení — konfigurace a způsob, jak vybrat správné pro každý dotaz.
  • Oddělené repository třídyMerchantRepository pro aktivní data, LegacyMerchantRepository pro archivní.
  • Jasná sémantika dotazů — "hledám aktivního obchodníka" vs. "hledám historický záznam".
  • Klíčové rozhodnutí pro PM — potřebujeme někdy dotazovat historická a aktivní data dohromady (reporting, ML scoring)? Pokud ano, náklady jsou výrazně vyšší.
Legacy layer: archivní DB nikdy nedostane schema migration. Nový vývojář musí pochopit, že existují dva světy dat — dokumentace tohoto rozhraní je kritická.
Application Merchant Repository Legacy Repository ACTIVE DB LEGACY DB
05 / Doporučení

Moje preference — s podmínkami

Nestojím si za jednou odpovědí bez toho, aniž bych věděl víc. Ale mohu říct, jak bych uvažoval při volbě.

?
Vstupují historická data do scoringu?
Klíčová otázka pro volbu přístupu
Pokud ANO
Plnohodnotný archiv s dotazovacím přístupem. Legacy layer nestačí.
?
Jak rychle rostou data dál?
Lineárně
Archivace je nevyhnutelná. Tooling přístup jen oddálí problém.
0
Tolerance na downtime při migraci?
Nulová
Online schema change tooling — bez ohledu na zvolený archivační přístup.
Moje hypotéza: Legacy layer + oddělená archivní DB. Legacy layer dává jasnou architektonickou hranici v kódu, oddělená DB dává jasnou fyzickou hranici. Ale toto je hypotéza k ověření — ne rozhodnutí.
scoring data? ANO NE Legacy Layer + Archive DB
06 / Roadmapa

Tři fáze — nejdřív fakta

T 1–3
Fáze 0 — Discoveryžádný kód
Stack, verze, konfigurace DB. EXPLAIN ANALYZE top 10 dotazů. Délka dnešních migrací. S PM: definice "historická data". Přístup k nim v kódu.
T 4–10
Fáze 1 — Pilotjedna tabulka
Nejproblematičtější tabulka s nejjednodušším přístupovým vzorem. Archive pipeline, LegacyRepository (read-only, bez ORM magic). Měříme čas migrace vs. baseline.
T 11–22
Fáze 2 — Rolloutzbylé tabulky
Rozšíření na ostatní problematické tabulky. Optimalizace indexů na nyní menší tabulky. Automatizace archivačního procesu a monitoring pipeline.
Fáze 0 není "zdržování" — je to investice, která ušetří týdny špatně zvolené implementace.
Fáze 0 2–3 týdny Fáze 1 4–6 týdnů Fáze 2 2–3 měsíce Later
07 / Lidé

Vedení týmu
& spolupráce s PM

TÝM

Nepřijdu s hotovým řešením

Přijdu s analýzou z Fáze 0 a pozvu tým k diskusi o variantách. Vývojáři, kteří s archivem budou pracovat každý den, vidí věci, které já nevidím.

PM

Technický dluh v jazyce byznysu

PM nerozumí délce ALTER TABLE. Ale rozumí: "Migrace zastaví onboarding obchodníků na dvě hodiny. Za 12 měsíců to budou čtyři."

  • Kapacitní split — explicitní dohoda s PM: např. 30 % sprintu na tuto iniciativu. Bez explicitní dohody iniciativa vždy prohraje s urgentními tickety.
  • Archivační linie = businessové rozhodnutí — co je "staré" musí definovat PM, ne technika. PM musí být zapojený od začátku.
  • Transparentní roadmapa — PM vidí kdykoli, kde jsme. Kompromisy se diskutují, ne blokují automaticky ani tiše kapitulují.
TEAM LEAD dev1 dev2 dev3 PRO DUCT
08 / Metriky

Definuji před začátkem, ne po

Primární metriky — výsledek iniciativy
MetrikaCílPoznámka
Délka schema migration na hlavní DB< 5 minBaseline měřím v Fázi 0
p99 latence klíčových dotazů onboarding flowbez regresůMěřím před a po
Počet DB-related incidentů za měsíctrend ↓Definuji, co je "DB incident"
Sekundární — průběh iniciativy
MetrikaPoznámka
Velikost hlavní DB a trend růstuZpomalení trendu po archivaci
Úspěšnost archivační pipeline% runů bez chyby, od prvního dne pilotu
Čas onboardingu nového vývojářeProxy metrika kvality dokumentace
Anti-metrika
"Počet archivovaných záznamů" není cíl. Je to prostředek. Prezentovat ho jako úspěch je chyba — signalizuje, že jsme ztratili ze zřetele, co vlastně řešíme.
Sdílím otevřeně
Všechny metriky sdílím s týmem i s PM. Ne jako reporting — jako společný jazyk o tom, zda jdeme správným směrem.
09 / Nad rámec zadání

Otázky, které zadání neřeší

Zadání říká "alespoň" — takže si dovolím přidat věci, které by mě trápily.

GDPR a compliance — Shoptet Pay pracuje s daty obchodníků v platebním prostředí. Právo na výmaz platí i pro archivovaná data. Pokud je archivní DB "zmrazená", jak řešíme delete request? Toto musí být zodpovězeno před implementací.
ML
Scoring a historická data — Pokud ML model nebo scoring engine potřebuje historii obchodníka jako vstup, pak legacy layer nestačí. Zjistím v Fázi 0 a přizpůsobím přístup.
🧪
Jak testujeme archivaci? — Migrace produkčních dat je nebezpečná operace. Nesmíme ji testovat na produkci. Potřebujeme staging s anonymizovaným dumpem produkce.
Rollback plán — Konkrétní postup, kdo co dělá a jak dlouho to trvá. Ne "obnovíme z backupu" — ale krok za krokem, před prvním archivačním jobem v produkci.
📖
Developer experience — Dokumentace není volitelná. Je součástí Definition of Done pro každý archivační milestone. Jinak se legacy layer stane "tím záhadným kódem, do kterého se nikdo nechce dívat".
ML 🧪 📖 more ... zadání
10 / Závěr

Shrnutí přístupu

1
Nejdřív fakta — stack, metriky, přístupové vzorce. Bez toho děláme architektonická rozhodnutí poslepu.
2
Problém je životní cyklus dat, ne objem. Toto rámování určuje celou strategii.
3
Legacy layer je architektonický vzor, ne technologická volba. Technologie se přizpůsobí.
4
Pilot na jedné tabulce — validujeme přístup, měříme výsledek, pak teprve rollout.
5
Archivační linie je businessové rozhodnutí — PM musí být u toho.
6
Dokumentace je součástí deliverable — ne afterthought. Je to podmínka, bez které iniciativa vyschne.

Toto je 3–6 měsíců disciplinovaného, inkrementálního přístupu — kde každá fáze přinese hmatatelný výsledek a kde nikdy nezastavíme delivery produktu. Těším se na diskusi.

navigace
Shoptet Pay — Team Lead

Case Study
Engineering Team Lead

Jak vést databázovou refaktorizaci, aniž bychom zastavili produkt

(a proč to není jen technický problém).

Nikolai Baranov
nikolai.baranov@proton.me · +420 777 611 516
Březen 2026
01 / Nejdřív co nevím

Než navrhnu cokoliv konkrétního

Musím říct jednu věc na rovinu: nevím, na čem aplikace běží. A není to detail. V inzerátu na pozici se zmiňuje MariaDB — a pokud je to pravda, část technického přemýšlení, které by platilo pro PostgreSQL, tady prostě neplatí.

Proč záleží, jestli je to MariaDB nebo PostgreSQL: MariaDB (zejména v Galera Clusteru) koordinuje DDL operace jinak než PostgreSQL — ALTER TABLE v Galera je ve výchozím stavu blokující operace přes celý cluster (TOI mode). Nástroje jako pt-online-schema-change nebo gh-ost fungují s MariaDB, ale mají svá specifika. Pokud běží na Galera, archivační pipeline musí respektovat cluster sémantiku.

Každé níže popsané řešení dávám k dispozici jako konceptuální rámec — konkrétní implementace závisí na odpovědi na tuhle otázku. První věc, kterou udělám: zjistím přesnou technologii, verzi, konfiguraci. Nebudu to hádat.

02 / Jak o problému přemýšlím

Problém není objem dat

Zadání popisuje symptomy: pomalé migrace, nestabilita při velkém objemu, zpomalení delivery. Ale kořen problému je jiný.

Máme jednu tabulku, která obsluhuje dva fundamentálně odlišné případy použití. Aktivní data — záznamy obchodníků, kteří procházejí onboardingem, kde se schema mění spolu s produktem. A historická data — záznamy, které jsou de facto mrtvé: už se nemění, přistupuje se k nim zřídka a jejich schéma nemusí jít nikam.

Tyto dva světy mají odlišný životní cyklus, odlišnou frekvenci přístupu a odlišnou potřebu flexibility. Proto každá změna schématu — která se týká jen aktivních dat — musí projet přes miliony historických řádků, které s tou změnou nemají nic společného.

Neřešíme "jak zvládnout velký objem dat". Řešíme jak oddělit životní cykly dat tak, aby vývoj produktu mohl jít rychle, aniž by historická data za to platila.
03 / Tři konceptuální přístupy

Dříve než technologie

Než skočím na konkrétní technologie, je důležité pochopit, že existují tři různé konceptuální přístupy k tomuto problému — a každý z nich má jiné důsledky pro kód aplikace, provoz a tým.

A

Zlevnit migrace (tooling)

Necháme data tam, kde jsou, ale používáme nástroje (pt-osc, gh-ost), které dělají schema migrations online a bez dlouhého locku. Kód se nemění — problém růstu dat zůstává, jen ho oddálíme.

B

Archivační vzor

Přesuneme historická data do jiného úložiště. Hlavní DB zůstane malá. Kód musí vědět, kde hledat — potřebuje dvě připojení, dvě repository vrstvy, nebo smart routing.

C

Legacy layer přístup

Definujeme čáru v písku. Historická data jsou zmrazena, přistupuje se k nim přes dedikovanou read-only vrstvu v kódu. Archivní DB nikdy nedostane schema migration. Nový kód pracuje jen s aktivními daty.

Legacy layer jako architektonický vzor: nejde o technologii — je to architektonické rozhodnutí. Archivní DB nikdy nepotřebuje schema migrations. Nový kód je psán výhradně proti aktivním datům. Kontrakt je jasný: legacy data jsou read-only, forever. Nevýhoda: nový vývojář musí pochopit, že existují dva světy — dokumentace tohoto rozhraní je kritická.
04 / Co to znamená pro kód aplikace

Dopad na každodenní práci vývojářů

Toto je podle mě nejdůležitější část celé case study — a v diskusích o databázovém škálování se na ni zapomíná. Technologické rozhodnutí je sekundární. Klíčová otázka je: jak tato architektura ovlivní denní práci vývojářů?

Pokud přesuneme historická data do jiné DB, aplikace potřebuje dvě konfigurace DB připojení, oddělené repository třídy (MerchantRepository pro aktivní data, LegacyMerchantRepository pro archivní), jasnou sémantiku dotazů a rozhodnutí o tom, zda archivní data jsou dostupná přes stejné API nebo přes separátní "legacy" endpoint.

Klíčové rozhodnutí pro PM, ne pro techniku: Potřebujeme někdy dotazovat historická a aktivní data dohromady — například pro reporting nebo ML scoring? Pokud ano, náklady na udržení dvou DB jsou výrazně vyšší, protože potřebujeme JOIN přes hranice databází. Pokud ne, je to naopak čisté a jednoduché.
05 / Co bych doporučil

Moje preference — s podmínkami

Nestojím si za jednou odpovědí bez toho, aniž bych věděl víc o konkrétní situaci. Ale mohu říct, jak bych uvažoval při volbě přístupu.

?
Jsou historická data vstupem do aktivního rozhodování?
Pokud ANO
Potřebujeme plnohodnotný archiv s dotazovacím přístupem. Legacy layer je nedostatečný.
?
Jak rychle rostou data dál?
Lineárně
Archivace je nevyhnutelná. Tooling přístup ji jen oddálí.
0
Jaká je tolerance na downtime při migraci?
Nulová
Potřebujeme online schema change tooling — bez ohledu na zvolený archivační přístup.
Moje hypotéza — na základě zadání tak jak je popsáno: kombinace legacy layer přístupu a oddělené archivační DB. Legacy layer dává jasnou architektonickou hranici v kódu. Oddělená DB dává jasnou fyzickou hranici v infrastruktuře. Ale podmínky jsou: nevíme, jak je to s Galera, nevíme jestli historická data vstupují do scoringu, a nevíme, jak vypadá aplikační kód dnes. Tato preference je hypotéza k ověření — ne rozhodnutí.
06 / Prioritizace a postup

Tři fáze — nejdřív fakta

Nechci přijít s plánem, který ignoruje realitu delivery. Proto přistupuji takto:

T 1–3
Fáze 0 — Discoveryžádný kód
Zjistit přesný stack, verzi, konfiguraci DB — MariaDB standalone, Galera, nebo něco jiného? EXPLAIN ANALYZE na top 10 nejpomalejších dotazů — jsou pomalé kvůli objemu, nebo kvůli špatným indexům? Změřit délku dnešních schema migrations. S PM projít, co jsou historická data z businessového pohledu. Projít aplikační kód: jak se dnes přistupuje k historickým datům?
T 4–10
Fáze 1 — Pilotjedna tabulka
Vybrat nejproblematičtější tabulku s nejjednodušším přístupovým vzorem. Implementovat archivační pipeline pro tuto tabulku (cron nebo event-driven, záleží na stack). Vytvořit LegacyRepository vrstvu v kódu — záměrně jednoduchou, read-only, bez ORM magic. Neměnit aplikační API. Validace: schema migration na nyní menší tabulce — měříme čas, porovnáváme s baseline.
T 11–22
Fáze 2 — Rolloutzbylé tabulky
Rozšíření na zbývající problematické tabulky. Optimalizace indexů na hlavní DB — nyní menší tabulky, efektivnější indexy. Automatizace archivačního procesu a monitoring pipeline. Dokumentace je non-negotiable — co je legacy layer, proč existuje, jak s ním pracovat.
07 / Tým a spolupráce s PM

Vedení přes nejistotu

Nepřijdu s hotovým řešením a neoznamuji ho. Přijdu s analýzou z Fáze 0 a pozvu tým k diskusi o variantách. Vývojáři, kteří budou s archivační pipeline a legacy vrstvou pracovat každý den, vidí věci, které já nevidím — a pokud se cítí co-owners rozhodnutí, odvedou lepší práci.

Zároveň — rozhoduji. To není rozpor. Mohu přijmout challenge a změnit názor. Ale tým ode mě potřebuje jasnost, ne nekonečnou diskusi.

Navrhuji explicitní kapacitní split — například 30 % kapacity sprintu na tuto iniciativu, 70 % na produkt. Toto číslo není unilaterální — je to návrh k dohodě s PM. Bez explicitní dohody iniciativa vždy prohraje s urgentními tickety.
08 / Metriky

Definuji před začátkem, ne po

Všechny metriky sdílím otevřeně — s týmem i s PM.

Primární — výsledek iniciativy
MetrikaCílPoznámka
Délka schema migration na hlavní DB< 5 minBaseline měřím v Fázi 0
p99 latence klíčových dotazů onboarding flowbez regresůMěřím před a po
Počet DB-related incidentů za měsíctrend ↓Definuji, co je "DB incident"
Sekundární — průběh iniciativy
MetrikaPoznámka
Velikost hlavní DB a trend růstuZpomalení trendu po archivaci
Úspěšnost archivační pipeline% runů bez chyby, od pilotu
Čas onboardingu nového vývojářeProxy metrika kvality dokumentace
Anti-metrika
"Počet archivovaných záznamů" není cíl. Je to prostředek. Prezentovat ho jako úspěch je chyba — signalizuje, že jsme ztratili ze zřetele, co vlastně řešíme.
09 / Otázky, které zadání neřeší

Věci, které by mě trápily

Zadání říká "alespoň" — takže si dovolím přidat věci, o nichž bych chtěl mluvit.

GDPR a compliance historických dat — Shoptet Pay pracuje s daty obchodníků v platebním prostředí. Právo na výmaz (GDPR) platí i pro archivovaná data. Pokud archivní DB je "zmrazená", jak řešíme delete request? Toto musí být zodpovězeno před implementací, ne po.
ML
Co když historická data potřebujeme pro scoring? — Pokud ML model nebo scoring engine potřebuje historii obchodníka jako vstup pro aktivní rozhodování, pak legacy layer nestačí. Potřebujeme archivní DB, která je dotazovatelná — a to mění technologické a architektonické volby výrazně. Zjistím v Fázi 0.
🧪
Jak testujeme archivaci? — Migrace produkčních dat je nebezpečná operace. Nesmíme ji testovat na produkci. Potřebujeme staging prostředí s reprezentativními daty — anonymizovaný dump produkce. Bez toho je pilot v Fázi 1 hazard, ne inženýrství.
Rollback plán — Co se stane, pokud archivační pipeline způsobí ztrátu dat nebo poruší konzistenci? Konkrétní postup, kdo co dělá a jak dlouho to trvá — ne "obnovíme z backupu", ale krok za krokem, připravený ještě před tím, než pustím první archivační job do produkce.
📖
Developer experience a onboarding — Každý nový vývojář, který přijde do týmu, musí pochopit, že existují dvě DB a proč. Pokud to není dobře dokumentováno, legacy layer se stane "tím záhadným kódem, do kterého se nikdo nechce dívat". Dokumentace je součástí Definition of Done pro každý archivační milestone.
10 / Závěr

Shrnutí přístupu

Tohle není problém, který se vyřeší jedním víkendem nebo sprint hackathonem. Ale není to ani roky práce. Je to 3–6 měsíců disciplinovaného, inkrementálního přístupu — kde každá fáze přinese hmatatelný výsledek a kde nikdy nezastavíme delivery produktu na neurčito.

1
Nejdřív fakta — stack, metriky, přístupové vzorce. Bez toho děláme architektonická rozhodnutí poslepu.
2
Problém je životní cyklus dat, ne objem. Toto rámování určuje celou strategii.
3
Legacy layer je architektonický vzor, ne technologická volba. Technologie se přizpůsobí.
4
Pilot na jedné tabulce — validujeme přístup, měříme výsledek, pak teprve rollout.
5
Archivační linie je businessové rozhodnutí — PM musí být u toho.
6
Dokumentace je součástí deliverable — ne afterthought. Je to podmínka, bez které iniciativa vyschne.