Het valse dilemma van de moderne architectuur

Wanneer we een moderne applicatie bouwen met een statisch frontend, komen we vaak voor een binaire keuze te staan:

  • Alles inzetten op een Backend-as-a-Service oplossing(Supabase, Firebase) - eenvoudig maar beperkt

  • Bouw een volledige backend(Spring Boot, Node.js) - krachtig maar complex

Deze keuze is een valse dilemma. De hybride architectuur biedt een derde weg: gebruik elke technologie daar waar ze uitblinkt

Architecturale visie

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Traditionele Architectuur" {
  actor Utilisateur as user
  component "Frontend" as frontend #LightBlue
  component "Monolithische Backend" as backend #LightCoral {
    [Authentification]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [APIs Tierces]
  }
  database "Database" as db #LightGray

  user --> frontend
  frontend --> backend : Toutes les requêtes
  backend --> db
}

note right of backend
Alles loopt via de backend
zelfs de eenvoudige bewerkingen
⚠️ Single point of failure
⚠️ Complexiteit vanaf het begin
⚠️ Sterke koppeling
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Traditionele architectuur" {
  actor Utilisateur as user
  component "frontend" as frontend #LightBlue
  component "Monolithisch backend" as backend #LightCoral {
    [Authentification]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [APIs Tierces]
  }
  database "Database" as db #LightGray

  user --> frontend
  frontend --> backend : Toutes les requêtes
  backend --> db
}

note right of backend
  Tout passe par le backend
  même les opérations simples

  ⚠️ Point de congestion unique
  ⚠️ Complexité dès le départ
  ⚠️ Couplage fort
end note
@enduml

In deze aanpak moeten zelfs de eenvoudigste operaties (het lezen van een artikel, het aanmaken van een reactie) via uw backend verlopen. U betaalt de kost van de complexiteit vanaf de eerste dag.

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Pure BaaS-architectuur" {
  actor Utilisateur as user
  component "Frontend" as frontend #LightBlue
  cloud "Supabase / Firebase" as baas #LightGreen {
    [Auth]
    [Database]
    [Storage]
    [Edge Functions]
  }

  user --> frontend
  frontend --> baas : Toutes les opérations
}

note right of baas
Snelle ontwikkeling
Geen server om te beheren
⚠️ Beperkt voor complexe logica
⚠️ Vendor lock-in
⚠️ Beperkingen aan Edge Functions
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Zuivere BaaS-architectuur" {
  actor Utilisateur as user
  component "frontend" as frontend #LightBlue
  cloud "Supabase / Firebase" as baas #LightGreen {
    [Auth]
    [Database]
    [Storage]
    [Edge Functions]
  }

  user --> frontend
  frontend --> baas : Toutes les opérations
}

note right of baas
  Développement rapide
  Pas de serveur à gérer

  ⚠️ Limité pour logique complexe
  ⚠️ Vendor lock-in
  ⚠️ Edge Functions contraintes
end note
@enduml

Aan de andere kant is het volledig uitbesteden aan een BaaS in het begin aantrekkelijk, maar het toont al snel zijn grenzen zodra de bedrijfslogica complexer wordt.

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Utilisateur as user #LightBlue

package "Frontend-laag" {
  component "Statische Site JBake" as frontend #SkyBlue
}

package "Eenvoudige Laag (Supabase)" #LightGreen {
  component "Authenticatie" as auth
  component "Basis CRUD" as crud
  component "Bestandsopslag" as storage
  component "Realtime" as realtime
}

package "Business-laag (Spring Boot)" #Coral {
  component "Complexe Logica" as logic
  component "Orkestratie" as orchestration
  component "Geplande Taken" as jobs
  component "Integraties" as integrations
}

database "Gedeelde PostgreSQL" as db #LightGray

user --> frontend

frontend --> auth : OAuth2, JWT
frontend --> crud : Articles, Profils
frontend --> storage : Images, Fichiers
frontend --> realtime : Notifications

frontend --> logic : Calculs, Rapports
frontend --> orchestration : Workflows
logic --> integrations : Stripe, APIs
orchestration --> db
jobs --> db

crud --> db
auth --> db

note bottom of db
**Eén enkele bron van waarheid**
Gedeeld tussen Supabase en Spring Boot
end note

note right of auth
**Gratis tot 50k users**
Configuratie in enkele klikken
OAuth2 multi-providers
end note

note right of logic
**Alleen geactiveerd indien nodig**
Kotlin + Coroutines
Complexe transacties
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Utilisateur as user #LightBlue

package "frontendlaag" {
  component "Statische site JBake" as frontend #SkyBlue
}

package "Eenvoudige laag (Supabase)" #LightGreen {
  component "authenticatie" as auth
  component "CRUD Basis" as crud
  component "Bestandsopslag" as storage
  component "real-time" as realtime
}

package "Zakelijke laag (Spring Boot)" #Coral {
  component "complexe logica" as logic
  component "Orchestratie" as orchestration
  component "Geplande taken" as jobs
  component "Integraties" as integrations
}

database "PostgreSQL Gedeeld" as db #LightGray

user --> frontend

frontend --> auth : OAuth2, JWT
frontend --> crud : Articles, Profils
frontend --> storage : Images, Fichiers
frontend --> realtime : Notifications

frontend --> logic : Calculs, Rapports
frontend --> orchestration : Workflows
logic --> integrations : Stripe, APIs
orchestration --> db
jobs --> db

crud --> db
auth --> db

note bottom of db
  **Une seule source de vérité**
  Partagée entre Supabase et Spring Boot
end note

note right of auth
  **Gratuit jusqu'à 50k users**
  Configuration en quelques clics
  OAuth2 multi-providers
end note

note right of logic
  **Activé seulement si nécessaire**
  Kotlin + Coroutines
  Transactions complexes
end note
@enduml

De hybride architectuur scheidt duidelijk de verantwoordelijkheden op basis van de complexiteit en de aard van de bewerkingen.

Ontwerpprincipes

@startuml
skinparam backgroundColor #FEFEFE

rectangle "**Fase 1 : MVP**" #LightGreen {
  component "JBake + Supabase" as mvp
  note right
✓ Ontwikkeling in dagen
✓ Kosten: 0€
✓ Validatie concept
  end note
}

rectangle "**Fase 2 : Groei**" #LightYellow {
  component "JBake + Supabase\n+ Spring Boot (optioneel)" as growth
  note right
✓ Bedrijfslogica ontstaat
✓ Eerste geplande jobs
✓ Integraties van derden
  end note
}

rectangle "**Fase 3 : Scale**" #LightCoral {
  component "Volledige Architectuur" as scale
  note right
✓ Complexe orchestratie
✓ Geoptimaliseerde prestaties
✓ Gedistribueerde cache
  end note
}

mvp -down-> growth : Quand la complexité\nle justifie
growth -down-> scale : Optimisation\ncontinue
@enduml
@startuml
skinparam backgroundColor #FEFEFE

rectangle "Fase 1 : MVP" #LightGreen {
  component "JBake + Supabase" as mvp
  note right
    ✓ Développement en jours
    ✓ Coût : 0€
    ✓ Validation concept
  end note
}

rectangle "Fase 2 : Groei" #LightYellow {
  component "JBake + Supabase\n+ Spring Boot (optioneel)" as growth
  note right
    ✓ Logique métier émerge
    ✓ Premiers jobs planifiés
    ✓ Intégrations tierces
  end note
}

rectangle "Fase 3: Schalen" #LightCoral {
  component "Volledige architectuur" as scale
  note right
    ✓ Orchestration complexe
    ✓ Performances optimisées
    ✓ Cache distribué
  end note
}

mvp -down-> growth : Quand la complexité\nle justifie
growth -down-> scale : Optimisation\ncontinue
@enduml

Bouw geen Spring Boot als je het niet nodig hebt.Begin met Supabase, voeg Spring Boot toe wanneer de complexiteit dat rechtvaardigt.

@startmindmap
skinparam backgroundColor #FEFEFE
* Opérations\nApplicatives

left side

** Opérations Simples\n(Supabase)
***_ CRUD Standard
****_ Lecture
****_ Création
****_ Mise à jour
****_ Suppression
***_ Authentification
****_ Login/Logout
****_ OAuth2
****_ Gestion session
***_ Stockage
****_ Upload fichiers
****_ CDN automatique
***_ Temps Réel
****_ WebSocket
****_ Notifications

right side

** Opérations Complexes\n(Spring Boot)
***_ Logique Métier
****_ Calculs complexes
****_ Règles métier
****_ Validations avancées
***_ Orchestration
****_ Multi-services
****_ Transactions distribuées
****_ Saga patterns
***_ Tâches Planifiées
****_ Rapports périodiques
****_ Synchronisations
****_ Nettoyages
***_ Intégrations
****_ Paiements (Stripe)
****_ APIs tierces
****_ Services ML/AI

@endmindmap
@startmindmap
skinparam backgroundColor #FEFEFE
* Opérations\nApplicatives

left side

** Opérations Simples\n(Supabase)
***_ CRUD Standard
****_ Lecture
****_ Création
****_ Mise à jour
****_ Suppression
***_ Authentification
****_ Login/Logout
****_ OAuth2
****_ Gestion session
***_ Stockage
****_ Upload fichiers
****_ CDN automatique
***_ Temps Réel
****_ WebSocket
****_ Notifications

right side

** Opérations Complexes\n(Spring Boot)
***_ Logique Métier
****_ Calculs complexes
****_ Règles métier
****_ Validations avancées
***_ Orchestration
****_ Multi-services
****_ Transactions distribuées
****_ Saga patterns
***_ Tâches Planifiées
****_ Rapports périodiques
****_ Synchronisations
****_ Nettoyages
***_ Intégrations
****_ Paiements (Stripe)
****_ APIs tierces
****_ Services ML/AI

@endmindmap
@startuml
skinparam backgroundColor #FEFEFE

database "PostgreSQL" as db #LightGray {
  package "Schema: auth (Supabase)" #LightGreen {
    [users]
    [sessions]
    [identities]
  }

  package "Schema: public (Gedeeld)" #SkyBlue {
    [articles]
    [comments]
    [profiles]
  }

  package "Schema: business (Spring Boot)" #Coral {
    [orders]
    [payments]
    [reports]
  }
}

component "Supabase" as supabase #LightGreen
component "Spring Boot" as spring #Coral

supabase -down-> users : Gère
supabase -down-> sessions : Gère
supabase -down-> articles : Accède
supabase -down-> comments : Accède
supabase -down-> profiles : Accède

spring -down-> articles : Accède
spring -down-> profiles : Accède
spring -down-> orders : Gère
spring -down-> payments : Gère
spring -down-> reports : Gère

note right of db
**Voordelen:**
• Geen complexe synchronisatie
• JOINs mogelijk tussen tabellen
• Gegarandeerde consistentie
• Geünificeerde migraties
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

database "PostgreSQL" as db #LightGray {
  package "Schema: auth (Supabase)" #LightGreen {
    [users]
    [sessions]
    [identities]
  }

  package "Schema: publiek (gedeeld)" #SkyBlue {
    [articles]
    [comments]
    [profiles]
  }

  package "Schema: bedrijf (Spring Boot)" #Coral {
    [orders]
    [payments]
    [reports]
  }
}

component "Supabase" as supabase #LightGreen
component "Spring Boot" as spring #Coral

supabase -down-> users : Gère
supabase -down-> sessions : Gère
supabase -down-> articles : Accède
supabase -down-> comments : Accède
supabase -down-> profiles : Accède

spring -down-> articles : Accède
spring -down-> profiles : Accède
spring -down-> orders : Gère
spring -down-> payments : Gère
spring -down-> reports : Gère

note right of db
  **Avantages :**
  • Pas de synchronisation complexe
  • JOINs possibles entre tables
  • Cohérence garantie
  • Migrations unifiées
end note
@enduml

Door dezelfde PostgreSQL-instantie te delen, werken Supabase en Spring Boot op dezelfde gegevens zonder complexe synchronisatie.

Orkestratie van de fluxen

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Gebruiker" as user
participant "JBake" as jbake
participant "Supabase Auth" as auth
participant "Spring Boot" as spring
database "PostgreSQL" as db

== Authentification ==
user -> jbake : Clique "Inloggen"
jbake -> auth : Redirect OAuth2 (Google/GitHub)
auth -> user : Consent screen
user -> auth : Autorise
auth -> auth : Génère JWT
auth -> jbake : Retourne JWT + Refresh Token
jbake -> jbake : Stocke tokens (sessionStorage)

== Accès aux Ressources ==
group Opération Simple (CRUD)
  user -> jbake : Crée un article
  jbake -> db : POST avec JWT
  note right: Supabase Row Level Security\ncontroleert het JWT automatisch
  db -> jbake : Article créé
end

group Opération Complexe (Métier)
  user -> jbake : Génère un rapport
  jbake -> spring : POST /api/reports\navec JWT
  spring -> spring : Valide JWT Supabase
  spring -> spring : Extrait claims (user_id, roles)
  spring -> db : Requêtes complexes
  spring -> jbake : Rapport généré
end

note over auth, spring
**De JWT is universeel**
Gevalideerd door Supabase EN Spring Boot
Geen dubbele authenticatie
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Gebruiker" as user
participant "JBake" as jbake
participant "Supabase Auth" as auth
participant "Spring Boot" as spring
database "PostgreSQL" as db

== Authentification ==
user -> jbake : Clique "Inloggen"
jbake -> auth : Redirect OAuth2 (Google/GitHub)
auth -> user : Consent screen
user -> auth : Autorise
auth -> auth : Génère JWT
auth -> jbake : Retourne JWT + Refresh Token
jbake -> jbake : Stocke tokens (sessionStorage)

== Accès aux Ressources ==
group Opération Simple (CRUD)
  user -> jbake : Crée un article
  jbake -> db : POST avec JWT
  note right: Supabase Row Level Security\nvérifie le JWT automatiquement
  db -> jbake : Article créé
end

group Opération Complexe (Métier)
  user -> jbake : Génère un rapport
  jbake -> spring : POST /api/reports\navec JWT
  spring -> spring : Valide JWT Supabase
  spring -> spring : Extrait claims (user_id, roles)
  spring -> db : Requêtes complexes
  spring -> jbake : Rapport généré
end

note over auth, spring
  **Le JWT est universel**
  Valide par Supabase ET Spring Boot
  Pas de double authentification
end note
@enduml

Belangrijk puntEén authenticatieproces, één JWT, overal bruikbaar.

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Klant" as user
participant "JBake" as jbake
participant "Spring Boot" as spring
participant "Supabase DB" as supadb
participant "Stripe API" as stripe
participant "Voorraadservice" as inventory
participant "E-mailservice" as email
database "PostgreSQL" as db

user -> jbake : Passe commande
jbake -> spring : POST /api/orders/create

== Orchestration Spring Boot ==
spring -> db : BEGIN TRANSACTION

par Vérifications Parallèles
  spring -> inventory : Vérifier stock
  inventory -> spring : Stock OK
else
  spring -> db : Vérifier profil client
  db -> spring : Client vérifié
end

spring -> stripe : Créer Payment Intent
stripe -> spring : Intent créé (ID: pi_xxx)

spring -> db : Créer Order (status: PENDING)
db -> spring : Order créé

spring -> stripe : Confirmer paiement
stripe -> spring : Paiement confirmé

spring -> db : Update Order (status: PAID)
spring -> inventory : Décrémenter stock
spring -> db : COMMIT TRANSACTION

par Notifications Asynchrones
  spring -> email : Email confirmation
else
  spring -> supadb : Insert notification
  note right: Realtime-meldingen\nvia Supabase Realtime
end

spring -> jbake : Order confirmé
jbake -> user : Affiche confirmation

note over spring
**Spring Boot-verantwoordelijkheden:**
• ACID-transacties
• Multi-service orchestratie
• Automatische rollback bij fouten
• Beheer van edge cases
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "klant" as user
participant "JBake" as jbake
participant "Spring Boot" as spring
participant "Supabase DB" as supadb
participant "Stripe API" as stripe
participant "Voorraadservice" as inventory
participant "e-mailservice" as email
database "PostgreSQL" as db

user -> jbake : Passe commande
jbake -> spring : POST /api/orders/create

== Orchestration Spring Boot ==
spring -> db : BEGIN TRANSACTION

par Vérifications Parallèles
  spring -> inventory : Vérifier stock
  inventory -> spring : Stock OK
else
  spring -> db : Vérifier profil client
  db -> spring : Client vérifié
end

spring -> stripe : Créer Payment Intent
stripe -> spring : Intent créé (ID: pi_xxx)

spring -> db : Créer Order (status: PENDING)
db -> spring : Order créé

spring -> stripe : Confirmer paiement
stripe -> spring : Paiement confirmé

spring -> db : Update Order (status: PAID)
spring -> inventory : Décrémenter stock
spring -> db : COMMIT TRANSACTION

par Notifications Asynchrones
  spring -> email : Email confirmation
else
  spring -> supadb : Insert notification
  note right: Notification temps réel\nvia Supabase Realtime
end

spring -> jbake : Order confirmé
jbake -> user : Affiche confirmation

note over spring
  **Responsabilités Spring Boot :**
  • Transaction ACID
  • Orchestration multi-services
  • Rollback automatique si erreur
  • Gestion des cas limites
end note
@enduml

Wat Spring Boot brengtBetrouwbare orchestratie van complexe processen die meerdere systemen omvatten, met transactiegarantie.

@startuml
skinparam backgroundColor #FEFEFE

participant "Scheduler\n(Spring Boot)" as scheduler
participant "Rapportageservice" as report
participant "PostgreSQL" as db
participant "Externe API" as api
participant "E-mailservice" as email
participant "Supabase Storage" as storage

== Job Quotidien : 2h00 ==
activate scheduler
scheduler -> report : Déclenche génération rapport

activate report
report -> db : Récupère données\ndes dernières 24h
db -> report : Dataset

report -> report : Calculs & Agrégations
report -> report : Génération PDF

report -> storage : Upload PDF
storage -> report : URL publique

report -> email : Envoie aux admins\navec lien PDF
deactivate report

== Job Hebdomadaire : Dimanche 3h00 ==
scheduler -> report : Synchronisation externe

activate report
report -> api : Fetch données externes
api -> report : Nouvelles données

report -> db : Mise à jour tables
report -> db : Nettoyage données obsolètes
deactivate report

== Job Mensuel : 1er du mois ==
scheduler -> report : Facturation

activate report
report -> db : Liste clients actifs
report -> report : Calcul montants
report -> api : Génération factures (Stripe)
report -> email : Envoi factures
deactivate report

deactivate scheduler

note right of scheduler
**Onmogelijk met alleen Supabase**
Edge Functions niet geschikt
voor lange en terugkerende jobs
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

participant "Scheduler\n(Spring Boot)" as scheduler
participant "Rapport Service" as report
participant "PostgreSQL" as db
participant "externe API" as api
participant "e-mailservice" as email
participant "Supabase Opslag" as storage

== Job Quotidien : 2h00 ==
activate scheduler
scheduler -> report : Déclenche génération rapport

activate report
report -> db : Récupère données\ndes dernières 24h
db -> report : Dataset

report -> report : Calculs & Agrégations
report -> report : Génération PDF

report -> storage : Upload PDF
storage -> report : URL publique

report -> email : Envoie aux admins\navec lien PDF
deactivate report

== Job Hebdomadaire : Dimanche 3h00 ==
scheduler -> report : Synchronisation externe

activate report
report -> api : Fetch données externes
api -> report : Nouvelles données

report -> db : Mise à jour tables
report -> db : Nettoyage données obsolètes
deactivate report

== Job Mensuel : 1er du mois ==
scheduler -> report : Facturation

activate report
report -> db : Liste clients actifs
report -> report : Calcul montants
report -> api : Génération factures (Stripe)
report -> email : Envoi factures
deactivate report

deactivate scheduler

note right of scheduler
  **Impossible avec Supabase seul**
  Edge Functions non adaptées
  pour jobs longs et récurrents
end note
@enduml

Wat Spring Boot brengt: Betrouwbare geplande taken met statusbeheer, automatische nieuwe poging, en gegarandeerde uitvoering.

Beslissingsmatrix

@startuml
skinparam backgroundColor #FEFEFE

start

:Nouvelle fonctionnalité à implémenter;

if (CRUD simple ?) then (oui)
  :✅ **Supabase**;
  stop
else (non)
  if (Authentification ?) then (oui)
    :✅ **Supabase Auth**;
    stop
  else (non)
    if (Upload fichiers ?) then (oui)
      :✅ **Supabase Storage**;
      stop
    else (non)
      if (Temps réel ?) then (oui)
        :✅ **Supabase Realtime**;
        stop
      else (non)
        if (Row Level Security\nsuffisante ?) then (oui)
          :✅ **Supabase + Policies**;
          stop
        else (non)
          :⚠️ **Considérer Spring Boot**;
          #Coral:Passer à l'arbre\nde décision Spring Boot;
          stop
        endif
      endif
    endif
  endif
endif

@enduml
@startuml
skinparam backgroundColor #FEFEFE

start

:Nouvelle fonctionnalité à implémenter;

if (CRUD simple ?) then (oui)
  :✅ **Supabase**;
  stop
else (non)
  if (Authentification ?) then (oui)
    :✅ **Supabase Auth**;
    stop
  else (non)
    if (Upload fichiers ?) then (oui)
      :✅ **Supabase Storage**;
      stop
    else (non)
      if (Temps réel ?) then (oui)
        :✅ **Supabase Realtime**;
        stop
      else (non)
        if (Row Level Security\nsuffisante ?) then (oui)
          :✅ **Supabase + Policies**;
          stop
        else (non)
          :⚠️ **Considérer Spring Boot**;
          #Coral:Passer à l'arbre\nde décision Spring Boot;
          stop
        endif
      endif
    endif
  endif
endif

@enduml
@startuml
skinparam backgroundColor #FEFEFE

start

:Nouvelle fonctionnalité complexe;

if (Orchestration\nmulti-services ?) then (oui)
  :✅ **Spring Boot**;
  stop
else (non)
  if (Transaction ACID\ncritique ?) then (oui)
    :✅ **Spring Boot**;
    stop
  else (non)
    if (Job planifié ?) then (oui)
      :✅ **Spring Boot Scheduler**;
      stop
    else (non)
      if (Intégration API\ntierce complexe ?) then (oui)
        :✅ **Spring Boot**;
        stop
      else (non)
        if (Calculs lourds\n> 10 secondes ?) then (oui)
          :✅ **Spring Boot**;
          stop
        else (non)
          if (Cache distribué\nnécessaire ?) then (oui)
            :✅ **Spring Boot + Redis**;
            stop
          else (non)
            :⚠️ **Probablement Supabase**;
            #LightGreen:Revenir à l'arbre\nde décision Supabase;
            stop
          endif
        endif
      endif
    endif
  endif
endif

@enduml
@startuml
skinparam backgroundColor #FEFEFE

start

:Nouvelle fonctionnalité complexe;

if (Orchestration\nmulti-services ?) then (oui)
  :✅ **Spring Boot**;
  stop
else (non)
  if (Transaction ACID\ncritique ?) then (oui)
    :✅ **Spring Boot**;
    stop
  else (non)
    if (Job planifié ?) then (oui)
      :✅ **Spring Boot Scheduler**;
      stop
    else (non)
      if (Intégration API\ntierce complexe ?) then (oui)
        :✅ **Spring Boot**;
        stop
      else (non)
        if (Calculs lourds\n> 10 secondes ?) then (oui)
          :✅ **Spring Boot**;
          stop
        else (non)
          if (Cache distribué\nnécessaire ?) then (oui)
            :✅ **Spring Boot + Redis**;
            stop
          else (non)
            :⚠️ **Probablement Supabase**;
            #LightGreen:Revenir à l'arbre\nde décision Supabase;
            stop
          endif
        endif
      endif
    endif
  endif
endif

@enduml

Voorbeelden van architectuur per projecttype

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Persoonlijke Blog - 95% Supabase" {
  component "JBake" as jbake #SkyBlue

  package "Supabase (Gratis)" #LightGreen {
    [Auth: OAuth2 Google]
    [Articles (CRUD)]
    [Commentaires]
    [Images (Storage)]
    [Notifications Realtime]
  }

  package "Spring Boot (Optioneel)" #LightCoral {
    [Newsletter Mensuelle]
    note bottom: Alleen geplande taak
  }

  database "PostgreSQL" as db

  jbake --> [Auth: OAuth2 Google]
  jbake --> [Articles (CRUD)]
  jbake --> [Commentaires]
  jbake --> [Images (Storage)]
  jbake --> [Notifications Realtime]

  [Articles (CRUD)] --> db
  [Commentaires] --> db
  [Newsletter Mensuelle] --> db
}

note bottom of "Spring Boot (Optioneel)"
**Spring Boot niet verplicht**
Nieuwsbrief kan worden beheerd
door een externe service (Mailchimp)
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Persoonlijk blog - 95% Supabase" {
  component "JBake" as jbake #SkyBlue

  package "Supabase (Gratis)" #LightGreen {
    [Auth: OAuth2 Google]
    [Articles (CRUD)]
    [Commentaires]
    [Images (Storage)]
    [Notifications Realtime]
  }

  package "Spring Boot (Optioneel)" #LightCoral {
    [Newsletter Mensuelle]
    note bottom: Job planifié uniquement
  }

  database "PostgreSQL" as db

  jbake --> [Auth: OAuth2 Google]
  jbake --> [Articles (CRUD)]
  jbake --> [Commentaires]
  jbake --> [Images (Storage)]
  jbake --> [Notifications Realtime]

  [Articles (CRUD)] --> db
  [Commentaires] --> db
  [Newsletter Mensuelle] --> db
}

note bottom of "Spring Boot (Optioneel)"
  **Spring Boot pas obligatoire**
  Newsletter peut être gérée
  par un service tiers (Mailchimp)
end note
@enduml

vonnis: 100% Supabase is ruimschoots voldoende.

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "SaaS-applicatie - Hybride Architectuur" {
  component "JBake / React" as frontend #SkyBlue

  package "Supabase" #LightGreen {
    [Auth Multi-tenant]
    [Profils Utilisateurs]
    [Données Simples]
    [Storage Documents]
  }

  package "Spring Boot" #Coral {
    [Facturation (Stripe)]
    [Analytics Avancées]
    [Rapports Mensuels]
    [Quotas & Limites]
    [Webhooks Stripe]
  }

  cloud "Externe Diensten" {
    [Stripe API]
    [SendGrid Email]
  }

  database "Gedeelde PostgreSQL" as db

  frontend --> [Auth Multi-tenant]
  frontend --> [Profils Utilisateurs]
  frontend --> [Données Simples]
  frontend --> [Facturation (Stripe)]
  frontend --> [Analytics Avancées]

  [Auth Multi-tenant] --> db
  [Profils Utilisateurs] --> db
  [Données Simples] --> db

  [Facturation (Stripe)] --> db
  [Facturation (Stripe)] --> [Stripe API]
  [Analytics Avancées] --> db
  [Rapports Mensuels] --> db
  [Rapports Mensuels] --> [SendGrid Email]
  [Webhooks Stripe] ..> [Stripe API] : Écoute
}

note right of "Spring Boot"
**Noodzakelijk voor:**
• Abonnementbeheer
• Recurrente facturering
• Dynamische quota's
• Complexe analytics
• Betrouwbare webhooks
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "SaaS-toepassing - hybride architectuur" {
  component "JBake / React" as frontend #SkyBlue

  package "Supabase" #LightGreen {
    [Auth Multi-tenant]
    [Profils Utilisateurs]
    [Données Simples]
    [Storage Documents]
  }

  package "Spring Boot" #Coral {
    [Facturation (Stripe)]
    [Analytics Avancées]
    [Rapports Mensuels]
    [Quotas & Limites]
    [Webhooks Stripe]
  }

  cloud "Externe diensten" {
    [Stripe API]
    [SendGrid Email]
  }

  database "gedeelde PostgreSQL" as db

  frontend --> [Auth Multi-tenant]
  frontend --> [Profils Utilisateurs]
  frontend --> [Données Simples]
  frontend --> [Facturation (Stripe)]
  frontend --> [Analytics Avancées]

  [Auth Multi-tenant] --> db
  [Profils Utilisateurs] --> db
  [Données Simples] --> db

  [Facturation (Stripe)] --> db
  [Facturation (Stripe)] --> [Stripe API]
  [Analytics Avancées] --> db
  [Rapports Mensuels] --> db
  [Rapports Mensuels] --> [SendGrid Email]
  [Webhooks Stripe] ..> [Stripe API] : Écoute
}

note right of "Spring Boot"
  **Nécessaire pour :**
  • Gestion abonnements
  • Facturation récurrente
  • Quotas dynamiques
  • Analytics complexes
  • Webhooks fiables
end note
@enduml

Vonnis: Noodzakelijke hybride architectuur. Supabase voor het belangrijkste, Spring Boot voor het kritieke gedeelte (betalingen, facturering).

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "E-commerce - 70% Spring Boot" {
  component "Storefront (JBake/React)" as frontend #SkyBlue

  package "Supabase" #LightGreen {
    [Auth Clients]
    [Catalogue Produits\n(lecture seule)]
    [Images Produits]
  }

  package "Spring Boot (Business Logica)" #Coral {
    [Gestion Commandes]
    [Paiements Stripe]
    [Gestion Stock]
    [Calcul Frais Port]
    [Génération Factures]
    [Synchronisation ERP]
    [Emails Transactionnels]
  }

  cloud "Integraties" {
    [Stripe]
    [Transporteur API]
    [ERP Externe]
  }

  database "PostgreSQL" as db

  frontend --> [Auth Clients]
  frontend --> [Catalogue Produits\n(lecture seule)]
  frontend --> [Gestion Commandes]

  [Auth Clients] --> db
  [Catalogue Produits\n(lecture seule)] --> db

  [Gestion Commandes] --> db
  [Paiements Stripe] --> [Stripe]
  [Gestion Stock] --> db
  [Calcul Frais Port] --> [Transporteur API]
  [Génération Factures] --> db
  [Synchronisation ERP] --> [ERP Externe]
  [Synchronisation ERP] --> db
}

note right of "Spring Boot (Business Logica)"
**Spring Boot onmisbaar:**
• Kritieke transacties
• Complexe orchestratie
• Meerdere integraties
• Wettelijke naleving
• Synchronisatie-jobs
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "E‑commerce - 70% Spring Boot" {
  component "Storefront (JBake/React)" as frontend #SkyBlue

  package "Supabase" #LightGreen {
    [Auth Clients]
    [Catalogue Produits\n(lecture seule)]
    [Images Produits]
  }

  package "Spring Boot (Zakelijke kern)" #Coral {
    [Gestion Commandes]
    [Paiements Stripe]
    [Gestion Stock]
    [Calcul Frais Port]
    [Génération Factures]
    [Synchronisation ERP]
    [Emails Transactionnels]
  }

  cloud "Integraties" {
    [Stripe]
    [Transporteur API]
    [ERP Externe]
  }

  database "PostgreSQL" as db

  frontend --> [Auth Clients]
  frontend --> [Catalogue Produits\n(lecture seule)]
  frontend --> [Gestion Commandes]

  [Auth Clients] --> db
  [Catalogue Produits\n(lecture seule)] --> db

  [Gestion Commandes] --> db
  [Paiements Stripe] --> [Stripe]
  [Gestion Stock] --> db
  [Calcul Frais Port] --> [Transporteur API]
  [Génération Factures] --> db
  [Synchronisation ERP] --> [ERP Externe]
  [Synchronisation ERP] --> db
}

note right of "Spring Boot (Zakelijke kern)"
  **Spring Boot indispensable :**
  • Transactions critiques
  • Orchestration complexe
  • Intégrations multiples
  • Conformité légale
  • Jobs de synchronisation
end note
@enduml

VerdictSpring Boot onmisbaar. Supabase alleen voor auth en catalogus.

@startuml
skinparam backgroundColor #FEFEFE

|Semaine 1-2|
start
:Créer projet Supabase;
:Configurer Auth (Google, GitHub);
:Définir schéma PostgreSQL initial;
:Implémenter CRUD de base sur JBake;
:Déployer MVP sur GitHub Pages;
note right
**Oplevering:** Functionele applicatie
**Kosten:** 0€
**Tijd:** 1-2 weken
end note

|Semaine 3-4|
:Observer utilisation réelle;
:Identifier limitations;

|Décision|
if (Logique complexe\némerge ?) then (non)
  |Supabase|
  :Continuer avec Supabase seul;
  :Ajouter Edge Functions si besoin;
  stop
else (oui)
  |Spring Boot|
  :Créer projet Spring Boot;
  :Configurer validation JWT Supabase;
  :Migrer logique complexe vers Spring Boot;
  note right
**Selectieve migratie**
Alleen dat wat complex is
  end note
endif

|Semaines suivantes|
:Déployer Spring Boot (Cloud Run, EC2);
:Connecter à PostgreSQL Supabase;
:Implémenter premiers jobs planifiés;
:Intégrer APIs tierces;

stop

note right
**Finale hybride architectuur**
Supabase + Spring Boot
in perfecte harmonie
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

|Semaine 1-2|
start
:Créer projet Supabase;
:Configurer Auth (Google, GitHub);
:Définir schéma PostgreSQL initial;
:Implémenter CRUD de base sur JBake;
:Déployer MVP sur GitHub Pages;
note right
  **Livrable :** Application fonctionnelle
  **Coût :** 0€
  **Temps :** 1-2 semaines
end note

|Semaine 3-4|
:Observer utilisation réelle;
:Identifier limitations;

|Décision|
if (Logique complexe\némerge ?) then (non)
  |Supabase|
  :Continuer avec Supabase seul;
  :Ajouter Edge Functions si besoin;
  stop
else (oui)
  |Spring Boot|
  :Créer projet Spring Boot;
  :Configurer validation JWT Supabase;
  :Migrer logique complexe vers Spring Boot;
  note right
    **Migration sélective**
    Seulement ce qui est complexe
  end note
endif

|Semaines suivantes|
:Déployer Spring Boot (Cloud Run, EC2);
:Connecter à PostgreSQL Supabase;
:Implémenter premiers jobs planifiés;
:Intégrer APIs tierces;

stop

note right
  **Architecture finale hybride**
  Supabase + Spring Boot
  en parfaite harmonie
end note
@enduml

Kosten en operationele overwegingen

@startuml
skinparam backgroundColor #FEFEFE

package "Geschatte Maandelijkse Kosten" {

  rectangle "MVP-fase\n(0-1000 gebruikers)" #LightGreen {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot: N/A]
    note bottom: **Totaal: 0€/maand**
  }

  rectangle "Groeifase\n(1k-10k gebruikers)" #LightYellow {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot (Cloud Run): 20-50€]
    [PostgreSQL (si séparé): 0-30€]
    note bottom: **Totaal: 20-80€/maand**
  }

  rectangle "Scale-fase\n(10k-100k gebruikers)" #LightCoral {
    [JBake (Netlify Pro): 19€]
    [Supabase Pro: 25€]
    [Spring Boot (instances multiples): 100-300€]
    [Redis Cache: 20-50€]
    [Monitoring: 20€]
    note bottom: **Totaal: 184-414€/maand**
  }
}

note right of "Scale-fase\n(10k-100k gebruikers)"
Op dit punt rechtvaardigen de inkomsten ruimschoots de kosten
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

package "Geschatte maandelijkse kosten" {

  rectangle "Fase MVP\n(0-1000 gebruikers)" #LightGreen {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot: N/A]
    note bottom: **Total: 0€/mois**
  }

  rectangle "Groeifase\n(1k-10k gebruikers)" #LightYellow {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot (Cloud Run): 20-50€]
    [PostgreSQL (si séparé): 0-30€]
    note bottom: **Total: 20-80€/mois**
  }

  rectangle "Fase-schaal\n(10k-100k gebruikers)" #LightCoral {
    [JBake (Netlify Pro): 19€]
    [Supabase Pro: 25€]
    [Spring Boot (instances multiples): 100-300€]
    [Redis Cache: 20-50€]
    [Monitoring: 20€]
    note bottom: **Total: 184-414€/mois**
  }
}

note right of "Fase-schaal\n(10k-100k gebruikers)"
  À ce stade, les revenus
  justifient largement les coûts
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

package "Wie Beheert Wat?" {

  rectangle "Beheerd door Supabase (0 inspanning)" #LightGreen {
    [Authentification]
    [Base de données]
    [Backups automatiques]
    [Scaling automatique]
    [Monitoring DB]
    [Sécurité DB]
  }

  rectangle "Beheerd door GitHub (0 inspanning)" #SkyBlue {
    [Hébergement site statique]
    [HTTPS/SSL]
    [CDN global]
    [Déploiement automatique]
  }

  rectangle "Te Beheren (Spring Boot)" #LightCoral {
    [Déploiement application]
    [Monitoring APM]
    [Logs centralisés]
    [Scaling horizontal]
    [Mises à jour sécurité]
  }
}

note bottom of "Te Beheren (Spring Boot)"
**Minimaliseerbaar met:**
• Cloud Run (serverless)
• Kubernetes (indien nodig)
• Managed services (RDS, etc.)
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

package "Wie beheert wat?" {

  rectangle "Beheerd door Supabase (0 inspanning)" #LightGreen {
    [Authentification]
    [Base de données]
    [Backups automatiques]
    [Scaling automatique]
    [Monitoring DB]
    [Sécurité DB]
  }

  rectangle "Beheerd door GitHub (0 inspanning)" #SkyBlue {
    [Hébergement site statique]
    [HTTPS/SSL]
    [CDN global]
    [Déploiement automatique]
  }

  rectangle "Te beheren (Spring Boot)" #LightCoral {
    [Déploiement application]
    [Monitoring APM]
    [Logs centralisés]
    [Scaling horizontal]
    [Mises à jour sécurité]
  }
}

note bottom of "Te beheren (Spring Boot)"
  **Minimisable avec :**
  • Cloud Run (serverless)
  • Kubernetes (si nécessaire)
  • Services managés (RDS, etc.)
end note
@enduml

Conclusie : Het perfecte evenwicht

De hybride Supabase + Spring Boot architectuur is geen compromis, het is eensynergie.

@startmindmap
skinparam backgroundColor #FEFEFE
* Architecture\nHybride

** Commencer Simple
***_ MVP avec Supabase
***_ 0€ de coût initial
***_ Validation rapide

** Évoluer Intelligemment
***_ Ajouter Spring Boot\nsi nécessaire
***_ Migration progressive
***_ Pas de refonte totale

** Exploiter les Forces
***_ Supabase: Simplicité
***_ Spring Boot: Puissance
***_ PostgreSQL: Source unique

** Minimiser la Complexité
***_ Pas de synchronisation
***_ Pas de duplication
***_ Architecture claire

** Optimiser les Coûts
***_ Gratuit au départ
***_ Scaling progressif
***_ ROI évident

@endmindmap
@startmindmap
skinparam backgroundColor #FEFEFE
* Architecture\nHybride

** Commencer Simple
***_ MVP avec Supabase
***_ 0€ de coût initial
***_ Validation rapide

** Évoluer Intelligemment
***_ Ajouter Spring Boot\nsi nécessaire
***_ Migration progressive
***_ Pas de refonte totale

** Exploiter les Forces
***_ Supabase: Simplicité
***_ Spring Boot: Puissance
***_ PostgreSQL: Source unique

** Minimiser la Complexité
***_ Pas de synchronisation
***_ Pas de duplication
***_ Architecture claire

** Optimiser les Coûts
***_ Gratuit au départ
***_ Scaling progressif
***_ ROI évident

@endmindmap

Wanneer kies je deze architectuur?

✅ Deze architectuur is ideaal als :

  • Je wilt snel starten (MVP in dagen, niet in maanden)

  • U verwacht een groei van de bedrijfscomplexiteit

  • U wilt de initiële kosten minimaliseren

  • U houdt van PostgreSQL en u wilt een enkele bron van waarheid

  • Je waardeert Kotlin en de Coroutines voor de zakelijke code

  • U wilt volledige vendor lock-in vermijden

Deze architectuur is NIET geschikt als :

  • Uw project is eenvoudig en zal dat blijven (persoonlijke blog → 100% Supabase is voldoende)

  • Je hebt al een gevestigde backend-stack die je beheerst

  • Je prefereert een traditionele monoliet

  • Je hebt .NET, Python of een andere backendtaal nodig.

@startuml
skinparam backgroundColor #FEFEFE

package "Volledige Hybride Architectuur" {

  actor "Gebruikers" as users

  rectangle "Frontend (Statisch)" #SkyBlue {
    [JBake / GitHub Pages]
    note right: Gratis, globaal CDN
  }

  rectangle "Eenvoudige Backend (Supabase)" #LightGreen {
    [Auth OAuth2]
    [CRUD APIs]
    [Storage]
    [Realtime]
    note right
Gratis tot 50k users
Nul serverconfiguratie
    end note
  }

  rectangle "Business Backend (Spring Boot)" #Coral {
    [Orchestration]
    [Jobs Planifiés]
    [Intégrations]
    [Transactions]
    note right
Alleen geactiveerd
indien nodig
    end note
  }

  database "PostgreSQL\nEnige Bron van Waarheid" as db #LightGray

  users --> [JBake / GitHub Pages]

  [JBake / GitHub Pages] --> [Auth OAuth2]
  [JBake / GitHub Pages] --> [CRUD APIs]
  [JBake / GitHub Pages] --> [Storage]
  [JBake / GitHub Pages] --> [Realtime]
  [JBake / GitHub Pages] --> [Orchestration]

  [Auth OAuth2] --> db
  [CRUD APIs] --> db
  [Orchestration] --> db
  [Jobs Planifiés] --> db
  [Intégrations] --> db
}

note bottom of db
**Eén basis, twee consumenten**
• Supabase voor het eenvoudige
• Spring Boot voor het complexe
• Geen synchronisatie vereist
end note

@enduml
@startuml
skinparam backgroundColor #FEFEFE

package "Volledige hybride architectuur" {

  actor "Gebruikers" as users

  rectangle "Frontend (Statisch)" #SkyBlue {
    [JBake / GitHub Pages]
    note right: Gratuit, CDN global
  }

  rectangle "simpele backend (Supabase)" #LightGreen {
    [Auth OAuth2]
    [CRUD APIs]
    [Storage]
    [Realtime]
    note right
      Gratuit jusqu'à 50k users
      Zéro configuration serveur
    end note
  }

  rectangle "Zakelijke backend (Spring Boot)" #Coral {
    [Orchestration]
    [Jobs Planifiés]
    [Intégrations]
    [Transactions]
    note right
      Activé uniquement
      si nécessaire
    end note
  }

  database "PostgreSQL\nUnieke bron van waarheid" as db #LightGray

  users --> [JBake / GitHub Pages]

  [JBake / GitHub Pages] --> [Auth OAuth2]
  [JBake / GitHub Pages] --> [CRUD APIs]
  [JBake / GitHub Pages] --> [Storage]
  [JBake / GitHub Pages] --> [Realtime]
  [JBake / GitHub Pages] --> [Orchestration]

  [Auth OAuth2] --> db
  [CRUD APIs] --> db
  [Orchestration] --> db
  [Jobs Planifiés] --> db
  [Intégrations] --> db
}

note bottom of db
  **Une seule base, deux consommateurs**
  • Supabase pour le simple
  • Spring Boot pour le complexe
  • Aucune synchronisation requise
end note

@enduml

Het Beste van twee werelden

Deze architectuur geeft u:

🚀 De snelheid van Supabase

  • Starten in uren, niet in weken

  • OAuth2-authenticatie in een paar klikken

  • Automatisch gegenereerde REST-APIs

  • Zero-configuratie van de server

💪 De kracht van Spring Boot

  • Kotlin en Coroutines voor elegante asynchrone code

  • Orchestratie van complexe bedrijfsprocessen

  • Geplande betrouwbare jobs

  • Gegarandeerde ACID-transacties

  • Volledig Spring-ecosysteem

💰 De Progressieve Economie

  • 0€ om te starten en te valideren

  • Kosten die de groei volgen

  • Geen prematuur over-engineering

🎯 de architecturale flexibiliteit

  • Progressieve migratie zonder herontwerp

  • Alleen Spring Boot toevoegen indien nodig

  • Geen totale vendor lock-in

  • Evolutieve architectuur

Verder gaan

Technische bronnen

Documentatie Supabase :

Spring Boot documentatie:

Aanvullende artikelen :

  • Beveiliging van API’s met JWT

  • Optimalisatie van PostgreSQL-prestaties

  • Progressieve migratiepatronen

  • Foutafhandeling in gedistribueerde architectuur

Werkelijke gebruikscases

Deze hybride architectuur wordt succesvol gebruikt in:

  • SaaS B2B: Authentificatie Supabase, facturatie Spring Boot

  • Marktplaatsen: Catalogus Supabase, transacties Spring Boot

  • contentplatforms: Artikelen Supabase, analytics Spring Boot

  • Interne hulpmiddelen: CRUD Supabase, werkstromen Spring Boot

Opstartchecklist

Phase 1 - Grondslagen (Week 1)

  • Supabase-account aanmaken - [ ] Configureer PostgreSQL-project - [ ] Auth inschakelen (Google, GitHub) - [ ] Definieer initieel schema - [ ] Row Level Security instellen - [ ] API’s testen sinds JBake

Fase 2 - MVP (Week 2-3)

  • Implementeren hoofdpagina’s - [ ] Integreren OAuth2-authenticatie - [ ] CRUD-formulieren maken - [ ] Opslag configureren voor bestanden - [ ] Deployen op GitHub Pages - [ ] Testen onder werkelijke omstandigheden

Fase 3 - Evolutie (Volgens behoeften)

  • Identificeer behoeften van complexe logica - [ ] Een Spring Boot project maken indien nodig - [ ] Configureer JWT-validatie Supabase - [ ] Verbinden met Supabase PostgreSQL - [ ] Migreer complexe functies - [ ] Implementeer geplande jobs - [ ] Spring Boot implementeren (Cloud Run, enz.)

Anti-Patterns om te vermijden

❌ Niet doen:

  • Dupliceren de gegevens tussen Supabase en Spring Boot

  • Maak twee aparte PostgreSQL-databases

  • Codeer de authenticatie zelf

  • Gebruik Spring Boot voor eenvoudige CRUD

  • Vanaf het begin over-architectureren

  • Negeer Row Level Security van Supabase

✅ Doe liever :

  • Een PostgreSQL-database delen

  • Laat Supabase de authenticatie regelen

  • Gebruik Spring Boot alleen voor de complexiteit

  • Begin eenvoudig, evolueer geleidelijk

  • Benut de sterke punten van elke technologie

  • Beveiligen met RLS op database-niveau

Ontwikkelingsperspectieven

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Huidige Architectuur" #SkyBlue {
  [JBake]
  [Supabase]
  [Spring Boot]
}

rectangle "Mogelijke Evoluties" #LightYellow {

  package "Performance" {
    [Redis Cache]
    [CDN pour Assets]
    [PostgreSQL Replicas]
  }

  package "Monitoring" {
    [Grafana]
    [Prometheus]
    [Sentry]
  }

  package "CI/CD" {
    [GitHub Actions]
    [Tests Automatisés]
    [Déploiement Continu]
  }

  package "Functionaliteiten" {
    [Search (ElasticSearch)]
    [Queue (RabbitMQ)]
    [Event Sourcing]
  }
}

[Spring Boot] .down.> [Redis Cache] : Peut ajouter
[Spring Boot] .down.> [Queue (RabbitMQ)] : Peut ajouter
[Spring Boot] .down.> [Search (ElasticSearch)] : Peut ajouter

[Supabase] .down.> [PostgreSQL Replicas] : Peut ajouter

note bottom
**Uitbreidbare architectuur**
Elke toevoeging is onafhankelijk
Geen globale herziening nodig
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

rectangle "Actuele architectuur" #SkyBlue {
  [JBake]
  [Supabase]
  [Spring Boot]
}

rectangle "Mogelijke evoluties" #LightYellow {

  package "prestatie" {
    [Redis Cache]
    [CDN pour Assets]
    [PostgreSQL Replicas]
  }

  package "Monitoring" {
    [Grafana]
    [Prometheus]
    [Sentry]
  }

  package "CI/CD" {
    [GitHub Actions]
    [Tests Automatisés]
    [Déploiement Continu]
  }

  package "Functies" {
    [Search (ElasticSearch)]
    [Queue (RabbitMQ)]
    [Event Sourcing]
  }
}

[Spring Boot] .down.> [Redis Cache] : Peut ajouter
[Spring Boot] .down.> [Queue (RabbitMQ)] : Peut ajouter
[Spring Boot] .down.> [Search (ElasticSearch)] : Peut ajouter

[Supabase] .down.> [PostgreSQL Replicas] : Peut ajouter

note bottom
  **Architecture extensible**
  Chaque ajout est indépendant
  Pas de refonte globale nécessaire
end note
@enduml

Horizontaal schalen

Wanneer uw toepassing groeit, schaalt de hybride architectuur natuurlijk:

Supabase:

  • Schaalt automatisch tot miljoenen operaties

  • Leesreplica’s voor leesprestaties

  • punt-in-tijd herstel voor veiligheid

Spring Boot:

  • Meerdere instanties achter load balancer

  • Stateless ontwerp vergemakkelijkt horizontale schaling

  • Kubernetes voor orchestratie indien nodig

PostgreSQL :

  • Partitionering voor grote tabellen

  • Verbindingpool (PgBouncer)

  • Sharding indien echt nodig (zeldzaam)

Architecturale getuigenissen

Startup SaaS (50k gebruikers)

_ We zijn begonnen met 100% Supabase. Bij 5k gebruikers hebben we Spring Boot alleen toegevoegd voor Stripe-facturatie en maandelijkse rapporten. Een jaar later zijn 80% van onze bewerkingen nog steeds via Supabase. Spring Boot behandelt alleen het kritieke deel. Deze scheiding heeft ons in staat gesteld om te schalen zonder herontwerp. _

E-learningplatform (10k gebruikers)

_ De OAuth2-authenticatie van Supabase heeft ons drie weken ontwikkeltijd bespaard. De automatisch gegenereerde API’s beheren ons volledige cursuscatalogus. Spring Boot wordt alleen gebruikt voor PDF-certificaten en voortgangs-e-mails. Eenvoudige, onderhoudbare, schaalbare architectuur. _

Marketplace B2B (3k gebruikers)

__ Spring Boot beheert de transacties tussen kopers en verkopers (kritiek). Supabase beheert alles andere: profielen, realtime berichten, documenten. Het feit dat ze dezelfde PostgreSQL-database delen, bespaart ons complexe synchronisatie. De beste architecturale keuze die we ooit hebben gemaakt. (Empty)

Samenvatting: Een modern architecturaal paradigma

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Oud Paradigma" #LightCoral {
  card "Alles in de Backend" {
    [Auth]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [Storage]
    [Realtime]
  }
  note bottom
Maximale complexiteit
vanaf dag 1
  end note
}

rectangle "Nieuw Paradigma" #LightGreen {
  card "Supabase\n(Gemak)" {
    [Auth]
    [CRUD Simple]
    [Storage]
    [Realtime]
  }

  card "Spring Boot\n(Differentiatie)" {
    [Logique Métier]
    [Jobs]
    [Intégrations]
  }

  note bottom
Progressieve complexiteit
alleen toegevoegd indien nodig
  end note
}

[Ancien Paradigme] -right-> [Nouveau Paradigme] : Évolution

@enduml
@startuml
skinparam backgroundColor #FEFEFE

rectangle "Oud paradigma" #LightCoral {
  card "Alles in de Backend" {
    [Auth]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [Storage]
    [Realtime]
  }
  note bottom
    Complexité maximale
    dès le jour 1
  end note
}

rectangle "Nieuw Paradigma" #LightGreen {
  card "Supabase\n(gemak)" {
    [Auth]
    [CRUD Simple]
    [Storage]
    [Realtime]
  }

  card "Spring Boot\n(Differentiatie)" {
    [Logique Métier]
    [Jobs]
    [Intégrations]
  }

  note bottom
    Complexité progressive
    ajoutée seulement si nécessaire
  end note
}

[Ancien Paradigme] -right-> [Nouveau Paradigme] : Évolution

@enduml

Het fundamentele principe :Bouw u niet wat al bestaat als een dienst. Concentreer u op wat uw toepassing onderscheidt.

De 80/20-regel

In de meeste toepassingen :

  • 80% van de operatieszijn standaard CRUD → Supabase

  • 20% van de bewerkingenvereisen zakelijke logica → Spring Boot

@startuml
skinparam backgroundColor #FEFEFE

package "Distributie van Operaties" {

  rectangle "80% - Standaard Operaties" #LightGreen {
    [Lecture de données]
    [Création d'entités]
    [Mise à jour simple]
    [Suppression]
    [Upload fichiers]
    [Authentification]

    note bottom: **Beheerd door Supabase**
  }

  rectangle "20% - Bedrijfslogica" #Coral {
    [Calculs complexes]
    [Workflows multi-étapes]
    [Transactions critiques]
    [Intégrations tierces]
    [Jobs planifiés]

    note bottom: **Beheerd door Spring Boot**
  }
}

note right
**Optimale focus :**
Uw ontwikkeltijd
geconcentreerd op de 20% die
uw product onderscheidt
end note
@enduml
@startuml
skinparam backgroundColor #FEFEFE

package "Distributie van de operaties" {

  rectangle "80% - Standaardoperaties" #LightGreen {
    [Lecture de données]
    [Création d'entités]
    [Mise à jour simple]
    [Suppression]
    [Upload fichiers]
    [Authentification]

    note bottom: **Géré par Supabase**
  }

  rectangle "20% - Bedrijfslogica" #Coral {
    [Calculs complexes]
    [Workflows multi-étapes]
    [Transactions critiques]
    [Intégrations tierces]
    [Jobs planifiés]

    note bottom: **Géré par Spring Boot**
  }
}

note right
  **Focus optimal :**
  Votre temps de développement
  concentré sur les 20% qui
  différencient votre produit
end note
@enduml

Finale conclusie

De hybride architectuur is geen technisch compromis, het is eenstrategische beslissing.

Het stelt je in staat om:

  • ✅ Snel starten met een functioneel MVP

  • ✅ Valideer uw markt zonder zware investering

  • ✅ Geleidelijk evolueren wanneer de complexiteit het vereist

  • Beheers uw kosten bij elke stap

  • ✅ Het beste uit elke technologie halen

  • ✅ Vermijd voortijdig over-engineering

  • ✅ Behoud de flexibiliteit voor de toekomst

Zij vertegenwoordigt :

  • pragmatisme: Elke technologie waarin ze uitblinkt

  • 🚀Snelheid: minimale time-to-market

  • 💰economie: Kosten afgestemd op waarde

  • 🔮 schaalbaarheidArchitectuur die met u groeit

  • 🛡️robuustheid: Bewezen en betrouwbare diensten

Uw Volgende Stap

Als deze architectuur u aanspreekt, hier kunt u beginnen:

  1. Maak een Supabase-account aan(gratis)

  2. Definieer uw minimale gegevensschema

  3. Configureer de OAuth2-authenticatie

  4. Maak uw eerste JBake-pagina die de API gebruikt

  5. Implementeer op GitHub Pages

U zult een functioneel MVP hebben ineen paar dagen.



De hybride architectuur is de kunst om precies te bouwen wat nodig is, wanneer het nodig is.



Gerelateerde artikelen