reading time: 12 minutes

Rather than choosing between the simplicity of Supabase and the power of Spring Boot, why not combine the two? Discover a hybrid architecture that leverages the best of each technology.

tap

[]

The false dilemma of modern architecture

When building a modern application with a static frontend, we often find ourselves faced with a binary choice:

  • Bet everything on a Backend-as-a-Service solution(Supabase, Firebase) - simple but limited

  • Build a complete backend(Spring Boot, Node.js) - powerful but complex

This choice is a false dilemma. Hybrid architecture offers a third way: using each technology where it excels.

Architectural Vision

Traditional Architecture: Monolithic

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Traditional Architecture" {
  actor Utilisateur as user
  component "Frontend" as frontend #LightBlue
  component "Monolithic 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 this approach, even the simplest operations (reading an article, creating a comment) must go through your backend. You pay the cost of complexity from day one.

The BaaS Architecture: All Delegate

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Pure BaaS Architecture" {
  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

Conversely, delegating everything to a BaaS is appealing at first but quickly shows its limitations as soon as the business logic becomes more complex.

The Hybrid Architecture: Separation of Responsibilities

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Utilisateur as user #LightBlue

package "Frontend Layer" {
  component "JBake Static Site" as frontend #SkyBlue
}

package "Simple Layer (Supabase)" #LightGreen {
  component "Authentication" as auth
  component "Basic CRUD" as crud
  component "File Storage" as storage
  component "Real Time" as realtime
}

package "Business Layer (Spring Boot)" #Coral {
  component "Complex Logic" as logic
  component "Orchestration" as orchestration
  component "Scheduled Jobs" as jobs
  component "Integrations" as integrations
}

database "Shared 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
  **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

The hybrid architecture clearly separates responsibilities according to the complexity and nature of the operations.

Design Principles

Principle 1: Start Simple, Evolve Intelligently

@startuml
skinparam backgroundColor #FEFEFE

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

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

rectangle "**Phase 3: Scale**" #LightCoral {
  component "Complete Architecture" 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

Do not build Spring Boot if you do not need it.Start with Supabase, add Spring Boot when the complexity justifies it.

Principle 2: Separation by Nature of Operation

@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

Principle 3: Single Source of Truth

@startuml
skinparam backgroundColor #FEFEFE

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

  package "Schema: public (Shared)" #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
  **Avantages :**
  • Pas de synchronisation complexe
  • JOINs possibles entre tables
  • Cohérence garantie
  • Migrations unifiées
end note
@enduml

By sharing the same PostgreSQL instance, Supabase and Spring Boot work on the same data without complex synchronization.

Flow orchestration

Flow 1: Centralized Authentication

@startuml
skinparam backgroundColor #FEFEFE
autonumber

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

== Authentification ==
user -> jbake : Clique "Log in"
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

Key point: One authentication process, one JWT, usable everywhere.

Flux 2: Orchestration of a Complex Business Process

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Client" as user
participant "JBake" as jbake
participant "Spring Boot" as spring
participant "Supabase DB" as supadb
participant "Stripe API" as stripe
participant "Inventory Service" as inventory
participant "Email Service" 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

What Spring Boot brings: Reliable orchestration of complex processes involving multiple systems with transactional guarantee.

Flux 3: Scheduled Jobs and Synchronizations

@startuml
skinparam backgroundColor #FEFEFE

participant "Scheduler\n(Spring Boot)" as scheduler
participant "Report Service" as report
participant "PostgreSQL" as db
participant "External API" as api
participant "Email Service" 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
  **Impossible avec Supabase seul**
  Edge Functions non adaptées
  pour jobs longs et récurrents
end note
@enduml

What Spring Boot bringsReliable scheduled jobs with state management, automatic retry, and guaranteed execution.

Decision Matrix

When to use Supabase?

@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

When to Use Spring Boot?

@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

Examples of Architecture by Project Type

Blog / Portfolio

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

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

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

  package "Spring Boot (Optional)" #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 (Optional)"
  **Spring Boot pas obligatoire**
  Newsletter peut être gérée
  par un service tiers (Mailchimp)
end note
@enduml

Verdict: 100% Supabase is more than enough.

SaaS application

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "SaaS Application - Hybrid Architecture" {
  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 "External Services" {
    [Stripe API]
    [SendGrid Email]
  }

  database "Shared 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

VerdictHybrid architecture required. Supabase for the essentials, Spring Boot for the critical part (payments, invoicing).

E-commerce

@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 (Core Business)" #Coral {
    [Gestion Commandes]
    [Paiements Stripe]
    [Gestion Stock]
    [Calcul Frais Port]
    [Génération Factures]
    [Synchronisation ERP]
    [Emails Transactionnels]
  }

  cloud "Integrations" {
    [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 (Core Business)"
  **Spring Boot indispensable :**
  • Transactions critiques
  • Orchestration complexe
  • Intégrations multiples
  • Conformité légale
  • Jobs de synchronisation
end note
@enduml

VerdictSpring Boot essential. Supabase for auth and catalog only.

Progressive Migration Strategy

@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

Costs and Operational Considerations

Cost Structure

@startuml
skinparam backgroundColor #FEFEFE

package "Estimated Monthly Costs" {

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

  rectangle "Growth Phase\n(1k-10k users)" #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 "Phase Scale\n(10k-100k users)" #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 "Phase Scale\n(10k-100k users)"
  À ce stade, les revenus
  justifient largement les coûts
end note
@enduml

Operational Responsibilities

@startuml
skinparam backgroundColor #FEFEFE

package "Who Manages What?" {

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

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

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

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

Conclusion: The Perfect Equilibrium

The hybrid Supabase + Spring Boot architecture is not a compromise, it’s asynergypython import sys data = sys.stdin.read() data = data.rstrip('\r\n') sys.stdout.write(data)

Key Principles to Remember

@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

When to Choose This Architecture?

✅ This architecture is ideal if:

  • You want to start quickly (MVP in days, not months)

  • You anticipate a growth in business complexity

  • You want to minimize initial costs

  • You love PostgreSQL and want a single source of truth

  • You appreciate Kotlin and Coroutines for the business code

  • You want to avoid total vendor lock-in

�❌ This architecture is NOT suitable if :

  • Your project is simple and will stay that way (personal blog → 100% Supabase is enough)

  • You already have an established backend stack that you master

  • You prefer a traditional monolith

  • You need .NET, Python, or another backend language

Final Overview

@startuml
skinparam backgroundColor #FEFEFE

package "Complete Hybrid Architecture" {

  actor "Users" as users

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

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

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

  database "PostgreSQL\nSingle Source of Truth" 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

The Best of Both Worlds

This architecture gives you :

🚀 The Velocity of Supabase

  • Starting in hours, not in weeks

  • OAuth2 authentication in a few clicks

  • Automatically generated REST APIs

  • Zero server configuration

�💪 The Power of Spring Boot

  • Kotlin and Coroutines for elegant asynchronous code

  • Orchestration of complex business processes

  • Reliable scheduled jobs

  • Guaranteed ACID transactions

  • Complete Spring ecosystem

�💰 The Progressive Economy

  • 0€ to start and validate

  • Costs that follow growth

  • No premature over-engineering

�🎯 Architectural Flexibility

  • Progressive migration without redesign

  • Adding Spring Boot only if necessary

  • No total vendor lock-in

  • evolutionary architecture

To Go Further

Technical Resources

Supabase Documentation:

Spring Boot Documentation:

Supplementary Articles :

  • Securing APIs with JWT

  • PostgreSQL performance optimization

  • Progressive migration patterns

  • Error handling in distributed architecture

Real Use Cases

This hybrid architecture is successfully used in:

  • SaaS B2B: Authentication Supabase, billing Spring Boot

  • Marketplaces: Supabase catalog, Spring Boot transactions

  • Content platforms: Articles Supabase, analytics Spring Boot

  • Internal tools: CRUD Supabase, workflows Spring Boot

Startup Checklist

Phase 1 - Foundations (Week 1)

  • Create Supabase account - [ ] Configure PostgreSQL project - [ ] Enable Auth (Google, GitHub) - [ ] Define initial schema - [ ] Configure Row Level Security - [ ] Test APIs from JBake

Phase 2 - MVP (Week 2-3)

  • Implement main pages - [ ] Integrate OAuth2 authentication - [ ] Create CRUD forms - [ ] Configure Storage for files - [ ] Deploy on GitHub Pages - [ ] Test in real conditions

Phase 3 - Evolution (As needed)

  • Identify complex logic needs - [ ] Create Spring Boot project if necessary - [ ] Configure Supabase JWT validation - [ ] Connect to Supabase PostgreSQL - [ ] Migrate complex features - [ ] Implement scheduled jobs - [ ] Deploy Spring Boot (Cloud Run, etc.)

Anti-Patterns to Avoid

❌ Do not:

  • Duplicate data between Supabase and Spring Boot

  • Create two separate PostgreSQL databases

  • Code the authentication yourself

  • Use Spring Boot for simple CRUD

  • Over-architect from the start

  • Ignore Row Level Security of Supabase

Better to:

  • Share a single PostgreSQL database

  • Let Supabase handle authentication

  • Use Spring Boot only for the complexity

  • Start simple, evolve gradually

  • Leverage the strengths of each technology

  • Secure with RLS at database level

Evolution prospects

Adding New Capabilities

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Current Architecture" #SkyBlue {
  [JBake]
  [Supabase]
  [Spring Boot]
}

rectangle "Possible Developments" #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 "Features" {
    [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

horizontal scaling

As your application grows, the hybrid architecture scales naturally:

Supabase:

  • Scale automatically up to millions of operations

  • Read replicas for read performance

  • Point-in-time recovery for security

Spring Boot:

  • Multiple instances behind load balancer

  • Stateless design facilitates horizontal scaling

  • Kubernetes for orchestration if needed

PostgreSQL :

  • Partitioning for large tables

  • Connection pooling (PgBouncer)

  • Sharding only if really necessary (rare)

Architectural Testimonies

SaaS startup (50k users)

_ We started 100% Supabase. At 5k users, we added Spring Boot only for Stripe billing and monthly reports. One year later, 80% of our operations still go through Supabase. Spring Boot handles only the critical part. This separation allowed us to scale without a rewrite. _

E-learning platform (10k users)

_ Supabase OAuth2 authentication saved us 3 weeks of development. The auto-generated APIs handle our entire course catalog. Spring Boot is only used for PDF certificates and progress emails. Simple, maintainable, scalable architecture. _

Marketplace B2B (3k users)

_ Spring Boot manages transactions between buyers and sellers (critical). Supabase handles everything else: profiles, real‑time messaging, documents. The fact that they share the same PostgreSQL database eliminates the need for complex synchronization on our end. This is the best architectural decision we have made. _

Synthesis: A Modern Architectural Paradigm

The hybrid Supabase + Spring Boot architecture represents a new paradigm :architectural specialization.

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Old Paradigm" #LightCoral {
  card "Everything in the Backend" {
    [Auth]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [Storage]
    [Realtime]
  }
  note bottom
    Complexité maximale
    dès le jour 1
  end note
}

rectangle "New Paradigm" #LightGreen {
  card "Supabase\n(Convenience)" {
    [Auth]
    [CRUD Simple]
    [Storage]
    [Realtime]
  }

  card "Spring Boot\n(Differentiation)" {
    [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

The fundamental principle:Don’t build what already exists as a service. Focus on what differentiates your application.

The 80/20 Rule

In most applications:

  • 80% of the operationsare standard CRUD → Supabase

  • 20% of operationsrequire business logic → Spring Boot

This natural rule justifies the hybrid architecture.

@startuml
skinparam backgroundColor #FEFEFE

package "Distribution of Operations" {

  rectangle "80% - Standard Operations" #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% - Business Logic" #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

Final Conclusion

Hybrid architecture is not a technical compromise, it’s astrategic decision.

It allows you to:

  • �✅ Start quickly with a functional MVP

  • �✅ Validate your market without heavy investment

  • �✅ Evolve gradually when complexity demands

  • �✅ Control your costs at every step

  • Leverage the best of each technology

  • ✅ Avoid premature over-engineering

  • ✅ Maintain flexibility for the future

She represents:

  • 🎯PragmatismEvery technology where she excels

  • 🚀Velocity: minimal time-to-market

  • �💰Economy: Costs aligned with value

  • �🔮Scalability: Architecture that grows with you

  • (No visible French text to translate)robustness: Proven and reliable services

Your Next Step

If this architecture speaks to you, here’s where to start:

  1. Create a Supabase account(free)

  2. Define your minimal data schema

  3. Configure the OAuth2 authentication

  4. Create your first JBake page that consumes the API

  5. Deploy to GitHub Pages

You will have a functional MVP ina few days.

Spring Boot will come naturally when you need it. Not before.


Hybrid architecture is the art of building exactly what is needed, when it is needed.

Good development! 🚀


Share this article if you think it can help other developers make the right architectural choices.

Related articles