Hybrid Architecture: The Best of Both Worlds with Supabase and Spring Boot
Published on 14 January 2026
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:
-
Create a Supabase account(free)
-
Define your minimal data schema
-
Configure the OAuth2 authentication
-
Create your first JBake page that consumes the API
-
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.