Przejdź do treści
Q
QuoteNode

Wiki

Stos technologiczny i uzasadnienie wyborow

Dlaczego QuoteNode korzysta z Java, Spring Boot i PostgreSQL oraz jakie kompromisy oznacza to dla hostingu i wydajnosci.

Stos technologiczny i uzasadnienie wyborow

Decyzje technologiczne w QuoteNode wynikaja z bezpieczenstwa, poprawnosci i dlugoterminowej utrzymywalnosci, a nie z pogoni za najnowszym frameworkiem czy minimalnym zuzyciem zasobow.

Ta strona wyjasnia, czego uzywamy, dlaczego wybralismy akurat to i co to oznacza dla deploymentu.

Dlaczego Java 25 i Spring Boot 4

Bezpieczenstwo jako glowny powod

QuoteNode pracuje na wrazliwych danych handlowych: rekordach klientow, strategiach cenowych, negocjacjach ofert i relacjach biznesowych. Stos technologiczny musi byc sprawdzony w srodowiskach, w ktorych blad bezpieczenstwa ma realne konsekwencje.

Java i Spring Boot to domyslny wybor w bankowosci, ubezpieczeniach, ochronie zdrowia i administracji panstwowej — czyli tam, gdzie bezpieczenstwo nie jest opcjonalne. To nie przypadek:

  • Dojrzaly model bezpieczenstwa — Spring Security zapewnia sprawdzona i audytowalna warstwe dla uwierzytelniania, autoryzacji, zarzadzania sesja, ochrony CSRF i naglowkow bezpieczenstwa. Nie trzeba budowac tych prymitywow od zera.
  • Type safety — silny system typow Javy wychwytuje cale klasy bledow juz na etapie kompilacji, ktore w jezykach dynamicznych stalyby sie bledami runtime. Przy wyliczaniu wartosci ofert, wielowalutowosci, VAT i rabatow to nie jest luksus.
  • Memory safety — JVM zapewnia automatyczne zarzadzanie pamiecia przez garbage collection, eliminujac przepelelnienia bufora, use-after-free i inne podatnosci korupcji pamieci znane z C/C++, a czasem tez z ekosystemow Go.
  • Dojrzaly ekosystem — biblioteki takie jak Flyway (migracje), Thymeleaf (szablony PDF), Hibernate (ORM) czy Testcontainers (testy integracyjne) sa utrzymywane przez organizacje z dlugim track recordem.

Dlaczego nie Go, Rust albo Node.js

Kazda z tych technologii bylaby rozsadnym wyborem dla innego produktu. Dla QuoteNode konkretnie:

  • Go — swietne do uslug sieciowych i narzedzi CLI, ale jego system typow jest slabszy, a modelowanie bardziej zlozonej logiki cenowej oraz deterministycznych obliczen wielowalutowych jest bardziej podatne na bledy. Ekosystem dla potrzeb enterprise (ORM, migracje, renderowanie PDF, frameworki security) jest tez mniej dojrzaly.
  • Rust — maksymalizuje wydajnosc i bezpieczenstwo pamieci, ale kosztem szybkosci developmentu i dojrzalosci ekosystemu dla aplikacji biznesowych. QuoteNode to platforma biznesowa typu CRUD-heavy, a nie projekt systems programming. Czasy kompilacji i prog wejscia spowolnilyby rozwoj bez proporcjonalnej korzysci.
  • Node.js — bardzo szybki do prototypowania, ale jednowatkowa wspolbieznosc, slabsza dyscyplina typow nawet przy TypeScript oraz rozdrobniony ekosystem czynia go slabszym wyborem dla security-critical platformy z obliczeniami finansowymi. Glebokie drzewo zaleznosci npm zwieksza tez ryzyko supply-chain.

Co to oznacza dla zuzycia zasobow

Aplikacje Java zuzywaja wiecej pamieci niz porownywalne uslugi w Go czy Rust. Backend QuoteNode potrzebuje zwykle 512 MB do 1.5 GB RAM, zaleznie od obciazenia i konfiguracji JVM. To swiadomy kompromis:

  • kompilator JIT JVM optymalizuje gorace sciezki po rozgrzaniu, dajac przepustowosc porownywalna z jezykami kompilowanymi natywnie przy stalej pracy,
  • pauzy garbage collectora sa pomijalne dla aplikacji single-tenant z typowym obciazeniem B2B,
  • dodatkowa pamiec kupuje bogatszy system typow, dojrzale prymitywy security, battle-tested biblioteki i szybszy rozwoj funkcji.

Dla aplikacji self-hosted, single-tenant, obslugujacej jedna organizacje, roznica miedzy 256 MB a 1 GB RAM jest operacyjnie nieistotna. Najtanszy VPS zdolny uruchomic Docker Compose uruchomi tez QuoteNode bez problemu.

PostgreSQL 16

PostgreSQL jest jedyna wspierana baza danych. To decyzja celowa:

  • ACID i transakcyjnosc — kazde wyliczenie oferty, zmiana statusu i zapis audytowy dzieja sie w poprawnej transakcji. Implementacja MVCC w PostgreSQL daje silne gwarancje izolacji.
  • JSON support — snapshoty ofert sa przechowywane w kolumnach JSONB, co pozwala wydajnie odpytywac historyczne dane ofert bez dodatkowego document store.
  • Rozszerzeniapgcrypto do serwerowego hashowania, pg_trgm do wyszukiwania pelnotekstowego po nazwach klientow i produktach.
  • Niezawodnosc — PostgreSQL ma dekady historii produkcyjnej w systemach finansowych i handlowych.
  • Narzedzia backupowepg_dump w formacie custom pozwala wykonywac spojne backupy online bez zatrzymywania aplikacji.

Szyfrowanie bazy

Wrazliwe pola sa szyfrowane na poziomie aplikacji przy uzyciu AES-256-GCM.

Zawsze szyfrowane (wymagany DB_ENCRYPTION_KEY):

  • sekrety TOTP (kody 2FA)
  • dane SMTP

Opcjonalnie szyfrowane (gdy ENCRYPT_PII=true):

  • PII klientow — nazwy, emaile, telefony, NIP / tax ID
  • PII osob kontaktowych — imiona, nazwiska, emaile, telefony
  • PII dostawcow — tax ID, email, telefon
  • PII kontaktow dostawcow — imiona, nazwiska, emaile, telefony
  • PII uzytkownikow — email, imie, nazwisko, numer telefonu
  • PII intentow zamowien — nazwa klienta, email, telefon

Gdy szyfrowanie PII jest wlaczone, zapytania exact-match uzywaja blind indexow HMAC-SHA256 przechowywanych obok ciphertextu zamiast zwyklego odpytywania kolumn. Wyszukiwanie pelnotekstowe spada wtedy do pol niebedacych PII (nazwy firm, cache display names). Zapytania typu LIKE po szyfrowanych kolumnach nie sa mozliwe z zalozenia — to swiadomy kompromis na rzecz ochrony danych.

Klucz szyfrujacy jest wyprowadzany z DB_ENCRYPTION_KEY przez SHA-256. Sam klucz nigdy nie trafia do bazy — istnieje tylko w pamieci aplikacji. Produkcyjny validator konfiguracji blokuje start z domyslnym kluczem developerskim. Dodatkowy validator startowy wykrywa niespojnosci miedzy flaga szyfrowania a realnym stanem bazy (na przyklad zaszyfrowane dane przy ENCRYPT_PII=false albo zly klucz) i odmawia startu, zeby zapobiec cichej korupcji danych.

Dostepne sa narzedzia CLI do operacji masowych: --pii-encrypt (zaszyfrowanie istniejacych danych jawnych), --pii-decrypt (powrot do tekstu jawnego) oraz --pii-rekey=<old-key> (przeszyfrowanie nowym kluczem).

Szyfrowanie at-rest dla calej bazy jest delegowane do infrastruktury hostingowej (LUKS, szyfrowane wolumeny EBS i podobne), bo daje lepsza wydajnosc niz szyfrowanie kolumn dla danych masowych.

Frontend Vue 3

Frontend jest aplikacja SPA zbudowana na Vue 3, Vite, PrimeVue 4 i Tailwind CSS 4:

  • Vue 3 — reaktywny, komponentowy interfejs z mocnym wsparciem TypeScript i dojrzalym ekosystemem.
  • PrimeVue 4 — biblioteka komponentow enterprise z dostepnymi, bogatymi funkcjonalnie tabelami, formularzami i dialogami. To pozwala nie odtwarzac zera zlozonych wzorcow UI.
  • Tailwind CSS 4 — utility-first styling z design tokens, co ulatwia utrzymanie spojnego jezyka wizualnego bez przerostu CSS.
  • Vite — szybki toolchain z hot module replacement dla lepszej produktywnosci w devie.
  • vue-i18n — pelna internacjonalizacja z aktywnym wsparciem dla angielskiego, polskiego, niemieckiego, francuskiego, hiszpanskiego, wloskiego i portugalskiego.

Frontend komunikuje sie z backendem wylacznie przez typowane REST API. Jest serwowany jako statyczne assety przez Caddy i nie ma bezposredniego dostepu do bazy.

Gotenberg

Generowanie PDF wykorzystuje Gotenberg, czyli usluge HTML-to-PDF oparta na Chromium:

  • poprawnie renderuje nowoczesny CSS (flexbox, grid, custom properties),
  • dziala jako osobny kontener, izolujac sam proces renderowania,
  • obsluguje paginacje, custom margins oraz szablony naglowkow i stopek,
  • nie wymaga bezposredniej zaleznosci od Chromium w backendzie — integracja odbywa sie przez HTTP API.

Kontener Gotenberg zuzywa zwykle 200-400 MB RAM. Jest aktywny tylko w czasie generowania PDF i moze miec limity zasobow ustawione po stronie Dockera.

Caddy

Caddy 2 pelni role reverse proxy z automatycznym HTTPS:

  • automatyczne wystawianie certyfikatow TLS przez Let’s Encrypt,
  • wsparcie HTTP/2 i HTTP/3,
  • prosty, deklaratywny konfig,
  • niski koszt zasobow (~20 MB RAM).

W deploymentach Coolify warstwa TLS jest obslugiwana przez proxy samego Coolify i kontener aplikacji nie potrzebuje oddzielnego reverse proxy.

Laczne wymagania zasobowe

KomponentRAM (typowo)DyskCPU
Backend (Java 25)512 MB – 1.5 GBminimalny1 rdzen
PostgreSQL 16256 MB – 512 MB1-10 GB danychwspoldzielone
Frontend statyczny~20 MB~50 MBpomijalne
Gotenberg200-400 MB~500 MBburst only
Caddy~20 MBminimalnypomijalne
Lacznie~1.5 – 2.5 GB~2-12 GB2 rdzenie

VPS z 4 GB RAM, 2 rdzeniami i 20 GB SSD spokojnie uruchomi kompletny stack QuoteNode dla zespolu 10-20 uzytkownikow. To odpowiednik okolo $10-20 miesiecznie — wyraznie mniej niz miesieczny koszt wielu SaaS CRM.

Idealne dla malych i srednich firm

QuoteNode jest projektowany dla organizacji majacych od 1 do 50 uzytkownikow:

  • Freelancerow i samodzielnych konsultantow, ktorzy potrzebuja profesjonalnych dokumentow ofertowych bez placenia za enterprise CRM.
  • Malych agencji (5-15 osob), ktore chca scentralizowanego zarzadzania klientami i ofertami wraz z widocznoscia pracy zespolowej.
  • Srednich firm (15-50 osob) z bardziej uporzadkowana sprzedaza, potrzebujacych analityki pipeline, RBAC i zgodnosci audytowej.

Model self-hosted eliminuje miesieczne oplaty per-seat, a jednoczesnie daje pelna kontrole nad danymi, brandingiem i konfiguracja security. Dla organizacji, ktore juz utrzymuja podstawowa infrastrukture serwerowa albo korzystaja z platform typu Coolify, deployment QuoteNode doklada minimalny narzut operacyjny.

Roadmap jezykowa

QuoteNode wspiera obecnie angielski, polski, niemiecki, francuski, hiszpanski, wloski i portugalski zarowno w UI aplikacji, jak i na wszystkich powierzchniach klientowskich (oferty, PDF-y, publiczne linki, emaile).

Aktualna lista wspieranych jezykow:

  • angielski (English)
  • polski (Polski)
  • niemiecki (Deutsch)
  • francuski (Francais)
  • hiszpanski (Espanol)
  • wloski (Italiano)
  • portugalski (Portugues)

Angielski i polski pozostaja obecnie referencyjnie kompletnymi lokalizacjami. Pozostale wspierane jezyki sa juz aktywne w produkcie i sa dalej rozszerzane w warstwie publicznej strony. Dlugoterminowym celem pozostaje pelne pokrycie glownych jezykow europejskich bez potrzeby przebudowy kodu — architektura i18n jest juz przygotowana na taki wzrost.

PDF-y ofert oraz strony linkow publicznych moga juz renderowac sie w dowolnym wspieranym locale niezaleznie od jezyka UI, dzieki czemu da sie prezentowac oferty klientom miedzynarodowym w ich preferowanym jezyku.

Last reviewed: Recently