Monolity
Baza pytań rekrutacyjnych i wiedzy. Filtruj, szukaj i sprawdzaj swoją wiedzę.
easymonolitharchitecturedeployment
Odpowiedź
Architektura monolityczna to pojedyncza wdrażalna aplikacja, w której moduły działają w jednym procesie i zwykle współdzielą jedną bazę danych. System buduje się, testuje i wdraża jako całość, co jest proste na początku, ale może prowadzić do silnych powiązań przy wzroście.
easymonolithtradeoffsscalability
Odpowiedź
Zalety: prostszy rozwój i wdrożenia, łatwe testowanie/debugowanie lokalne oraz silna spójność i proste transakcje. Wady: trudniej niezależnie skalować części systemu, wolniejsze cykle wdrożeń i rosnący kod może stać się silnie powiązany i trudniejszy do bezpiecznych zmian.
mediummodular-monolithboundariesmaintainability
Odpowiedź
Utrzymuj jasne granice modułów (np. domenowe), egzekwuj zasady zależności, utrzymuj cienkie warstwy i dodawaj testy automatyczne. Stosuj wewnętrzne API, ograniczaj współdzielony stan i regularnie refaktoruj, aby monolit pozostał modułowy i łatwy w zmianach.
mediummodular-monolitharchitectureevolution
Odpowiedź
Monolit modułowy to wciąż jedna jednostka wdrożeniowa, ale z silną separacją modułów. Każdy moduł posiada własną domenę i komunikuje się przez dobrze zdefiniowane interfejsy, co poprawia utrzymanie i ułatwia przyszłe wydzielanie usług.
hardmigrationstrangler-figmicroservices
Odpowiedź
Preferuj migrację krokową (Strangler Fig): wydzielaj po jednej funkcji/domenie za stabilnym API i dodaj dobre logi/metryki/tracing. Unikaj big‑bang rewrite’u; rozdzielaj dane i logikę stopniowo.
easymonolitharchitecturetradeoffs
Odpowiedź
Monolit to jedna jednostka wdrożeniowa (jedna aplikacja/serwis) zawierająca wiele modułów/funkcji. Często jest świetny na start, bo upraszcza development, testy i wdrożenia oraz ułatwia transakcje i debugowanie.
easymonolithmicroservicesteam-size
Odpowiedź
Gdy zespół jest mały, domena szybko się zmienia i chcesz szybko iterować przy prostych operacjach. Mikroserwisy zwykle opłacają się dopiero, gdy realnie potrzebujesz niezależnych wdrożeń/skalowania i masz jasne granice.
easymodular-monolithboundariesarchitecture
Odpowiedź
To wciąż jedna jednostka wdrożeniowa, ale z mocnymi granicami wewnętrznymi: moduły posiadają swoją domenę i komunikują się przez jasno zdefiniowane interfejsy. To poprawia utrzymanie i ułatwia przyszłe wydzielanie serwisów.
mediummaintainabilitymodularityrefactoring
Odpowiedź
Ustal jasne granice modułów (często domenowe), egzekwuj zasady zależności i utrzymuj cienkie warstwy. Dodaj testy automatyczne i regularnie refaktoruj, żeby kod pozostał modułowy i łatwy do zmian.
mediumscalingstatelessload-balancer
Odpowiedź
Zrób aplikację stateless (sesje w Redis/DB), uruchom wiele instancji za load balancerem i osobno skaluj bazę (indeksy, cache, read repliki). Zwróć uwagę na współdzielone zasoby jak pliki i joby w tle.
mediumfeature-flagsrolloutrelease
Odpowiedź
Feature flagi pozwalają włączać/wyłączać funkcje w runtime bez wdrożenia. Ułatwiają bezpieczne release’y (dark launch, rollout) i szybki rollback, ale wymagają sprzątania, żeby nie mieć „flag debt”.
hardstrangler-figmigrationmicroservices
Odpowiedź
Dodaj warstwę routingu, wybierz małą funkcję/domenę, wydziel ją za stabilnym API i stopniowo przełączaj ruch. Powtarzaj kroki „po plasterku” z monitoringiem i rollbackiem, aż stara ścieżka będzie do usunięcia.
harddatabasemigrationdata-ownership
Odpowiedź
Własność danych i spójność: kto jest właścicielem których tabel i jak utrzymać spójność w trakcie przejścia (dual writes/outbox/eventy). Migracja powinna być krokowa z jasnym momentem cutover i strategią rollback.
hardbounded-contextseamsdecomposition
Odpowiedź
Szukaj bounded contexts: funkcji z jasnym właścicielem, danymi i małą liczbą zależności. Zacznij od części, które często się zmieniają lub mają wyraźne potrzeby skalowania, i nie dziel na początku mocno sprzężonych fragmentów.
harddistributed-monolithcouplingmicroservices
Odpowiedź
To system podzielony na serwisy, ale nadal mocno sprzężony (wspólna baza, synchroniczne „gadatliwe” wywołania, skoordynowane wdrożenia). Unikasz przez jasną własność, asynchroniczność tam gdzie trzeba, stabilne kontrakty i niezależne wdrożenia.
easymonorepomonolithrepo-structure
Odpowiedź
Monorepo to strategia repozytorium (wiele projektów w jednym repo). Monolit to jednostka wdrożeniowa/runtime (jedna aplikacja). Możesz mieć monolit w monorepo albo mikroserwisy w monorepo.
mediummaintainabilitycouplingcode-smell
Odpowiedź
To kod bez jasnych granic i z dużą, przypadkową zależnością między częściami. Objawy: brak jasnej odpowiedzialności, losowe regresje po zmianach, dużo globalnego stanu i „wszystko zależy od wszystkiego”.
mediummodulesboundariesarchitecture-tests
Odpowiedź
Organizuj kod po funkcjach/domenach, zdefiniuj jasne publiczne API między modułami i ogranicz zależności (np. reguły pakietów, testy architektury). Trzymaj wspólne utilsy małe i unikaj „god modułów”.
harddb-migrationexpand-contractdeployment+1
Odpowiedź
Zastosuj expand/contract: najpierw dodaj nowy schemat (np. nullable kolumna/nowa tabela) i wdroż kod obsługujący stare i nowe; potem zmigruj dane; a na końcu usuń stare w kolejnej wersji. To minimalizuje downtime i wspiera rollback.
hardscalingmonolithqueues+1
Odpowiedź
Skaluj poziomo (wiele stateless instancji za load balancerem) i przenieś ciężkie zadania do asynchronicznych jobów/kolejek (background processing). Dodatkowo skaluj odczyty przez cache i repliki.
easystructuremodularitymonolith
Odpowiedź
Package-by-layer grupuje kod po warstwach technicznych (kontrolery/serwisy/repo). Package-by-feature grupuje kod po funkcji/domenie. Struktura feature-based często lepiej skaluje, bo powiązany kod jest razem i granice są czytelniejsze.
mediumjobsqueueworker+1
Odpowiedź
Użyj osobnego procesu workera (ta sama baza kodu, inny entrypoint) konsumującego kolejkę, z retry i idempotencją. To nie blokuje requestów web i daje lepszą kontrolę współbieżności oraz błędów.
mediumshared-codeownershipmodularity
Odpowiedź
Trzymaj utilsy blisko funkcji, która jest ich właścicielem, a wspólny kod wydzielaj dopiero, gdy realnie potrzebuje go wiele modułów. Preferuj małe, nazwane biblioteki ze znanym właścicielem zamiast jednego ogromnego `utils`.
hardcibuildcaching+1
Odpowiedź
Użyj cache (zależności i artefaktów builda), uruchamiaj testy/linty inkrementalnie dla zmienionych modułów i równoleglij joby. Pomaga też niezależność modułów, żeby nie przebudowywać wszystkiego po małej zmianie.
hardrefactoringincrementaltesting+1
Odpowiedź
Rób to krokowo: wybierz jedną granicę, dodaj testy wokół zachowania, refaktoruj za stabilnym interfejsem i wypuszczaj małe kroki. Planuj czas na dług techniczny i unikaj big-bang rewrite’u.
easymonolithdeploymentrelease+1
Odpowiedź
Single deployable oznacza, że wdrażasz jeden artefakt jako jedną całość (jedna wersja do zbudowania, przetestowania i wdrożenia). To upraszcza release’y i rollbacki oraz unika niedopasowania wersji między serwisami. Minusem jest większy blast radius, gdy coś pójdzie źle.
mediumtestingmonolithci+1
Odpowiedź
Trzymaj piramidę testów: dużo szybkich unit testów, mniej integracyjnych i mało E2E. W integracji testuj kluczowe “seamy” (DB, messaging) z realistycznymi zależnościami (np. Testcontainers) i dbaj o równoległość oraz stabilność. Unikaj jednego gigantycznego test-suite “testuje wszystko”.
mediummonolithmodularityboundaries+1
Odpowiedź
Organizuj kod po funkcjach/domenach (a nie tylko po warstwach technicznych), wystawiaj małe wewnętrzne API między modułami i zabraniaj “sięgania” do wnętrza innych modułów importami. Dodaj ownership (kto utrzymuje co) i checki architektoniczne (granice modułów), żeby granice nie rozjeżdżały się w czasie.
hardmonolithmulti-tenancysecurity+1
Odpowiedź
Typowe opcje: osobna baza per tenant (mocna izolacja, większy koszt), osobna schema per tenant (dobra izolacja, średnia złożoność) albo współdzielone tabele z `tenant_id` (najtańsze, najtrudniejsze do poprawnego egzekwowania). Niezależnie od podejścia musisz wszędzie wymuszać tenant scoping oraz dodać właściwe indeksy i checki bezpieczeństwa.
hardmonolithperformanceobservability+1
Odpowiedź
Zdefiniuj SLI wydajności (np. p95) i monitoruj je cały czas. Dodaj profiling/tracing dla wolnych endpointów, rób load testy krytycznych flow i ustaw budżety/alerty, żeby łapać regresje wcześnie. Feature flagi pomagają szybko wycofać zmianę, gdy trzeba.
easymonolithsloggingobservability
Odpowiedź
Structured logging oznacza, że logi mają stałe pola (np. JSON) typu `level`, `message`, `requestId`, `userId`. Pomaga, bo możesz je łatwo filtrować, wyszukiwać i łączyć między wieloma fragmentami kodu bez parsowania „losowego” tekstu.
mediummonolithsloggingrequest-id+1
Odpowiedź
Correlation ID (request ID) to unikalny identyfikator requestu, który trafia do logów. Generuj go na wejściu (middleware/filter HTTP) albo przyjmij z upstreamu, a potem przekazuj przez wszystkie warstwy oraz joby uruchomione przez ten request.
mediummonolithsmodular-monolithboundaries+1
Odpowiedź
Zdefiniuj granice modułów i reguły kierunku zależności (np. moduły funkcjonalne mogą zależeć od shared kernel, ale nie od siebie nawzajem). Wymuszaj to buildem (osobne moduły Gradle/Maven), testami architektury oraz wystawianiem stabilnych interfejsów/fasad zamiast sięgania do „wnętrzności”.
hardmonolithsdddevents+1
Odpowiedź
Pomagają rozsprzęgać moduły: jeden moduł publikuje event („OrderPlaced”), a inne reagują bez ścisłych zależności. Pułapki: decyzja sync vs async, niewrzucanie ciężkiej pracy do tej samej transakcji oraz niezawodność i idempotencja handlerów (event może się powtórzyć).
hardmonolithsboundariesdatabase+1
Odpowiedź
Traktuj tabele jako „własność” modułów: tylko właściciel zapisuje dane i wystawia dostęp przez swoje API/fasadę. Unikaj cross-module joinów „gdzie popadnie”; zamiast tego pobieraj dane przez moduł właściciela albo użyj domain events. Jeśli trzeba, wymuszaj to osobnymi schematami, granicami repozytoriów oraz code review/regułami architektury.