thời gian đọc : 12 minutes

Thay vì phải chọn giữa sự đơn giản của Supabase và sức mạnh của Spring Boot, tại sao không kết hợp cả hai? Khám phá một kiến trúc lai tận dụng những điểm tốt nhất của mỗi công nghệ.

Table of Contents

Ngụy biện lưỡng nan của Kiến trúc Hiện đại

Khi xây dựng một ứng dụng hiện đại với frontend tĩnh, chúng ta thường đứng trước một lựa chọn nhị phân:

  • Đặt cược tất cả vào một giải pháp Backend-as-a-Service(Supabase, Firebase) - đơn giản nhưng hạn chế

  • Xây dựng một backend hoàn chỉnh(Spring Boot, Node.js) - mạnh mẽ nhưng phức tạp

Sự lựa chọn này là một tình huống tiến thoái lưỡng nan giả tạo. Kiến trúc lai đề xuất một con đường thứ ba: sử dụng mỗi công nghệ ở nơi nó xuất sắc nhất.

Tầm nhìn kiến trúc

Kiến trúc Truyền thống: Đơn khối

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Kiến trúc truyền thống" {
  actor Utilisateur as user
  component "Frontend" as frontend #LightBlue
  component "Backend nguyên khối" as backend #LightCoral {
    [Authentification]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [APIs Tierces]
  }
  database "Cơ sở dữ liệu" as db #LightGray

  user --> frontend
  frontend --> backend : Tất cả các yêu cầu
  backend --> db
}

note right of backend
Tất cả đều đi qua backend
ngay cả những thao tác đơn giản
⚠️ Điểm tắc nghẽn duy nhất
⚠️ Phức tạp ngay từ đầu
⚠️ Liên kết chặt
end note
@enduml

Trong cách tiếp cận này, ngay cả những thao tác đơn giản nhất (đọc một bài viết, tạo một bình luận) cũng phải đi qua backend của bạn. Bạn phải trả giá cho sự phức tạp ngay từ ngày đầu tiên.

Kiến trúc BaaS: Tất cả đều được ủy thác

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Kiến trúc BaaS Thuần" {
  actor Utilisateur as user
  component "Frontend" as frontend #LightBlue
  cloud "Supabase / Firebase" as baas #LightGreen {
    [Auth]
    [Database]
    [Storage]
    [Edge Functions]
  }

  user --> frontend
  frontend --> baas : Tất cả các thao tác
}

note right of baas
Phát triển nhanh
Không cần quản lý máy chủ
⚠️ Hạn chế với logic phức tạp
⚠️ Ràng buộc nhà cung cấp
⚠️ Edge Functions bị hạn chế
end note
@enduml

Ngược lại, giao phó mọi thứ cho một BaaS thoạt đầu có vẻ hấp dẫn nhưng nhanh chóng bộc lộ giới hạn ngay khi logic nghiệp vụ trở nên phức tạp.

Kiến trúc lai: Phân tách trách nhiệm

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Utilisateur as user #LightBlue

package "Lớp Frontend" {
  component "Trang web tĩnh JBake" as frontend #SkyBlue
}

package "Lớp đơn giản (Supabase)" #LightGreen {
  component "Xác thực" as auth
  component "CRUD cơ bản" as crud
  component "Lưu trữ tệp" as storage
  component "Thời gian thực" as realtime
}

package "Lớp nghiệp vụ (Spring Boot)" #Coral {
  component "Logic phức tạp" as logic
  component "Điều phối" as orchestration
  component "Tác vụ theo lịch" as jobs
  component "Tích hợp" as integrations
}

database "PostgreSQL dùng chung" as db #LightGray

user --> frontend

frontend --> auth : OAuth2, JWT
frontend --> crud : Bài viết, Hồ sơ
frontend --> storage : Hình ảnh, Tệp
frontend --> realtime : Thông báo

frontend --> logic : Tính toán, Báo cáo
frontend --> orchestration : Quy trình làm việc
logic --> integrations : Stripe, APIs
orchestration --> db
jobs --> db

crud --> db
auth --> db

note bottom of db
**Một nguồn sự thật duy nhất**
Được chia sẻ giữa Supabase và Spring Boot
end note

note right of auth
**Miễn phí đến 50k người dùng**
Cấu hình chỉ với vài cú nhấp chuột
OAuth2 đa nhà cung cấp
end note

note right of logic
**Chỉ kích hoạt khi cần thiết**
Kotlin + Coroutines
Giao dịch phức tạp
end note
@enduml

Kiến trúc lai phân tách rõ ràng các trách nhiệm theo độ phức tạp và tính chất của các hoạt động.

Nguyên tắc thiết kế

Nguyên tắc 1: Bắt đầu đơn giản, phát triển thông minh

@startuml
skinparam backgroundColor #FEFEFE

rectangle "**Giai đoạn 1 : MVP**" #LightGreen {
  component "JBake + Supabase" as mvp
  note right
✓ Phát triển trong vài ngày
✓ Chi phí: 0€
✓ Xác thực khái niệm
  end note
}

rectangle "**Giai đoạn 2 : Tăng trưởng**" #LightYellow {
  component "JBake + Supabase\n+ Spring Boot (tùy chọn)" as growth
  note right
✓ Logic nghiệp vụ xuất hiện
✓ Những job được lập lịch đầu tiên
✓ Tích hợp bên thứ ba
  end note
}

rectangle "**Giai đoạn 3 : Mở rộng**" #LightCoral {
  component "Kiến trúc hoàn chỉnh" as scale
  note right
✓ Điều phối phức tạp
✓ Hiệu năng được tối ưu hóa
✓ Bộ nhớ đệm phân tán
  end note
}

mvp -down-> growth : Khi sự phức tạp\nbiện minh cho điều đó
growth -down-> scale : Tối ưu hóa\nliên tục
@enduml

Đừng xây dựng Spring Boot nếu bạn không cần đến nó.Bắt đầu với Supabase, thêm Spring Boot khi độ phức tạp đòi hỏi.

Nguyên tắc 2: Phân tách theo Bản chất Hoạt động

@startmindmap
skinparam backgroundColor #FEFEFE
* Hoạt động\nÁp dụng

left side

** Công việc đơn giản\n(Supabase)
***_ CRUD Tiêu chuẩn
****_ Bài giảng
****_ sự tạo ra
****_ Cập nhật
****_ Xóa
***_ Xác thực
****_ Đăng nhập/Logout
****_ OAuth2
****_ Quản lý phiên
***_ Lưu trữ
****_ Upload tệp tin
****_ CDN tự động
***_ thời gian thực
****_ WebSocket
****_ Thông báo

right side

** Các thao tác phức tạp\n(Spring Boot)
***_ Logic nghiệp vụ
****Tính toán phức tạp
****_ Quy tắc nghiệp vụ
****Xác thực nâng cao
***_ Điều phối
****_ Dịch vụ đa dạng
****_ Giao dịch phân tán
****_ Mẫu Saga
***_ Nhiệm vụ đã lên lịch
****Báo cáo định kỳ
****_ Đồng bộ hóa
****Vệ sinh
***_ Tích hợp
****_ Thanh toán (Stripe)
****_ APIs phần ba
****Dịch vụ ML/AI

@endmindmap

Nguyên tắc 3: Một nguồn sự thật duy nhất

@startuml
skinparam backgroundColor #FEFEFE

database "PostgreSQL" as db #LightGray {
  package "Lược đồ: auth (Supabase)" #LightGreen {
    [users]
    [sessions]
    [identities]
  }

  package "Lược đồ: public (Dùng chung)" #SkyBlue {
    [articles]
    [comments]
    [profiles]
  }

  package "Lược đồ: business (Spring Boot)" #Coral {
    [orders]
    [payments]
    [reports]
  }
}

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

supabase -down-> users : Quản lý
supabase -down-> sessions : Quản lý
supabase -down-> articles : Truy cập
supabase -down-> comments : Truy cập
supabase -down-> profiles : Truy cập

spring -down-> articles : Truy cập
spring -down-> profiles : Truy cập
spring -down-> orders : Quản lý
spring -down-> payments : Quản lý
spring -down-> reports : Quản lý

note right of db
**Ưu điểm:**
• Không cần đồng bộ phức tạp
• Có thể có JOINs giữa các bảng
• Đảm bảo tính nhất quán
• Các migration được hợp nhất
end note
@enduml

Bằng cách chia sẻ cùng một instance PostgreSQL, Supabase và Spring Boot làm việc trên cùng dữ liệu mà không cần đồng bộ hóa phức tạp.

Điều phối các Luồng

Luồng 1: Xác thực tập trung

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Người dùng" as user
participant "JBake" as jbake
participant "Supabase Auth" as auth
participant "Spring Boot" as spring
database "PostgreSQL" as db

== Authentification ==
user -> jbake : Clique "Đăng nhập"
jbake -> auth : Chuyển hướng OAuth2 (Google/GitHub)
auth -> user : Màn hình đồng ý
user -> auth : Cho phép
auth -> auth : Tạo JWT
auth -> jbake : Trả về JWT + Refresh Token
jbake -> jbake : Lưu trữ token (sessionStorage)

== Accès aux Ressources ==
group Opération Simple (CRUD)
  user -> jbake : Tạo một bài viết
  jbake -> db : POST với JWT
  note right: Supabase Row Level Security\ntự động kiểm tra JWT
  db -> jbake : Bài viết đã được tạo
end

group Opération Complexe (Métier)
  user -> jbake : Tạo một báo cáo
  jbake -> spring : POST /api/reports\nvới JWT
  spring -> spring : Xác nhận JWT Supabase
  spring -> spring : Trích xuất yêu cầu bồi thường (user_id, vai trò)
  spring -> db : Truy vấn phức tạp
  spring -> jbake : Báo cáo đã được tạo
end

note over auth, spring
**JWT là phổ quát**
Được xác thực bởi Supabase VÀ Spring Boot
Không có xác thực double
end note
@enduml

Điểm chính: Một quy trình xác thực duy nhất, một JWT duy nhất, có thể sử dụng ở mọi nơi.

Luồng 2: Điều phối một Quy trình Nghiệp vụ Phức tạp

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor "Máy khách" as user
participant "JBake" as jbake
participant "Spring Boot" as spring
participant "Supabase CSDL" as supadb
participant "Stripe API" as stripe
participant "Dịch vụ tồn kho" as inventory
participant "Dịch vụ email" as email
database "PostgreSQL" as db

user -> jbake : Đặt hàng
jbake -> spring : POST /api/orders/create

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

par Vérifications Parallèles
  spring -> inventory : Kiểm tra tồn kho
  inventory -> spring : Tồn kho OK
else
  spring -> db : Kiểm tra hồ sơ khách hàng
  db -> spring : Khách hàng đã được xác minh
end

spring -> stripe : Tạo Payment Intent
stripe -> spring : Đã tạo Intent (ID: pi_xxx)

spring -> db : Tạo Order (status: PENDING)
db -> spring : Đã tạo đơn hàng

spring -> stripe : Xác nhận thanh toán
stripe -> spring : Thanh toán đã được xác nhận

spring -> db : Cập nhật đơn hàng (trạng thái: PAID)
spring -> inventory : Giảm tồn kho
spring -> db : COMMIT TRANSACTION

par Notifications Asynchrones
  spring -> email : Xác nhận email
else
  spring -> supadb : Chèn thông báo
  note right: Thông báo thời gian thực\nqua Supabase Realtime
end

spring -> jbake : Đơn hàng đã được xác nhận
jbake -> user : Hiển thị xác nhận

note over spring
**Trách nhiệm Spring Boot:**
• Giao dịch ACID
• Điều phối đa dịch vụ
• Tự động rollback nếu có lỗi
• Xử lý các trường hợp biên
end note
@enduml

Những gì Spring Boot mang lại: Điều phối đáng tin cậy các quy trình phức tạp liên quan đến nhiều hệ thống với đảm bảo giao dịch.

Luồng 3: Tác vụ theo lịch và Đồng bộ hóa

@startuml
skinparam backgroundColor #FEFEFE

participant "Bộ lập lịch\n(Spring Boot)" as scheduler
participant "Dịch vụ báo cáo" as report
participant "PostgreSQL" as db
participant "Bên ngoài API" as api
participant "Dịch vụ email" as email
participant "Supabase Lưu trữ" as storage

== Job Quotidien : 2:00 ==
activate scheduler
scheduler -> report : Kích hoạt tạo báo cáo

activate report
report -> db : Lấy dữ liệu\ntrong 24 giờ qua
db -> report : Bộ dữ liệu

report -> report : Tính toán & Tổng hợp
report -> report : Tạo PDF

report -> storage : Tải lên PDF
storage -> report : URL publique

report -> email : Gửi cho các quản trị viên\nvới liên kết PDF
deactivate report

== Job Hebdomadaire : Chủ nhật 3h00 ==
scheduler -> report : Đồng bộ hóa bên ngoài

activate report
report -> api : Lấy dữ liệu bên ngoài
api -> report : Dữ liệu mới

report -> db : Cập nhật bảng
report -> db : Dọn dẹp dữ liệu lỗi thời
deactivate report

== Job Mensuel : Ngày 1 của tháng ==
scheduler -> report : Xuất hóa đơn

activate report
report -> db : Danh sách khách hàng đang hoạt động
report -> report : Tính toán số tiền
report -> api : Tạo hóa đơn (Stripe)
report -> email : Gửi hóa đơn
deactivate report

deactivate scheduler

note right of scheduler
**Không thể chỉ với Supabase**
Edge Functions không phù hợp
cho các tác vụ chạy lâu và lặp lại
end note
@enduml

Những gì Spring Boot mang lại: Các tác vụ theo lịch đáng tin cậy với quản lý trạng thái, tự động thử lại và đảm bảo thực thi.

Ma trận Quyết định

Khi nào nên sử dụng Supabase?

@startuml
skinparam backgroundColor #FEFEFE

start

:Tính năng mới cần triển khai;

if (CRUD simple ?) then (oui)
  :✅ **Supabase**;
  stop
else (non)
  if (Authentification ?) then (oui)
    :✅ **Supabase Xác thực**;
    stop
  else (non)
    if (Upload fichiers ?) then (oui)
      :✅ **Supabase Lưu trữ**;
      stop
    else (non)
      if (Temps réel ?) then (oui)
        :✅ **Supabase Thời gian thực**;
        stop
      else (non)
        if (Row Level Security\nsuffisante ?) then (oui)
          :✅ **Supabase + Chính sách**;
          stop
        else (non)
          :⚠️ **Cân nhắc Spring Boot**;
          #Coral:Passer à l'arbre\nde décision Spring Boot;
          stop
        endif
      endif
    endif
  endif
endif

@enduml

Khi nào nên sử dụng Spring Boot?

@startuml
skinparam backgroundColor #FEFEFE

start

:Tính năng mới phức tạp;

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)
            :⚠️ **Có lẽ là Supabase**;
            #LightGreen:Revenir à l'arbre\nde décision Supabase;
            stop
          endif
        endif
      endif
    endif
  endif
endif

@enduml

Ví dụ về Kiến trúc theo Loại Dự án

Blog / Hồ sơ năng lực

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Blog Cá nhân - 95% Supabase" {
  component "JBake" as jbake #SkyBlue

  package "Supabase (Miễn phí)" #LightGreen {
    [Auth: OAuth2 Google]
    [Articles (CRUD)]
    [Commentaires]
    [Images (Storage)]
    [Notifications Realtime]
  }

  package "Spring Boot (Tùy chọn)" #LightCoral {
    [Newsletter Mensuelle]
    note bottom: Chỉ công việc đã lên lịch
  }

  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 (Tùy chọn)"
**Spring Boot không bắt buộc**
Bản tin có thể được quản lý
bởi một dịch vụ bên thứ ba (Mailchimp)
end note
@enduml

Phán quyết: 100% Supabase là quá đủ.

Ứng dụng SaaS

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Ứng dụng SaaS - Kiến trúc Hybrid" {
  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 "Dịch vụ bên ngoài" {
    [Stripe API]
    [SendGrid Email]
  }

  database "PostgreSQL dùng chung" 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"
**Cần thiết cho:**
• Quản lý thuê bao
• Lập hóa đơn định kỳ
• Hạn mức động
• Phân tích phức tạp
• Webhook đáng tin cậy
end note
@enduml

Phán quyết: Kiến trúc lai là cần thiết. Supabase cho phần chính yếu, Spring Boot cho phần trọng yếu (thanh toán, lập hóa đơn).

Thương mại điện tử

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Thương mại điện tử - 70% Spring Boot" {
  component "Cửa hàng trực tuyến (JBake/React)" as frontend #SkyBlue

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

  package "Spring Boot (Nghiệp vụ cốt lõi)" #Coral {
    [Gestion Commandes]
    [Paiements Stripe]
    [Gestion Stock]
    [Calcul Frais Port]
    [Génération Factures]
    [Synchronisation ERP]
    [Emails Transactionnels]
  }

  cloud "Tích hợp" {
    [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 (Nghiệp vụ cốt lõi)"
**Spring Boot không thể thiếu:**
• Giao dịch trọng yếu
• Điều phối phức tạp
• Tích hợp nhiều hệ thống
• Tuân thủ pháp lý
• Tác vụ đồng bộ
end note
@enduml

Phán quyết: Spring Boot không thể thiếu. Supabase chỉ dùng cho xác thực và danh mục.

Chiến lược di cư dần dần

@startuml
skinparam backgroundColor #FEFEFE

|Semaine 1-2|
start
:Tạo dự án Supabase;
:Cấu hình Auth (Google, GitHub);
:Xác định lược đồ PostgreSQL ban đầu;
:Triển khai CRUD cơ bản trên JBake;
:Triển khai MVP trên GitHub Pages;
note right
**Sản phẩm bàn giao:** Ứng dụng hoạt động được
**Chi phí:** 0€
**Thời gian:** 1-2 tuần
end note

|Semaine 3-4|
:Quan sát việc sử dụng thực tế;
:Xác định các hạn chế;

|Décision|
if (Logique complexe\némerge ?) then (non)
  |Supabase|
  :Tiếp tục chỉ với Supabase;
  :Thêm Edge Functions nếu cần;
  stop
else (oui)
  |Spring Boot|
  :Tạo dự án Spring Boot;
  :Cấu hình xác thực JWT Supabase;
  :Di chuyển logic phức tạp sang Spring Boot;
  note right
**Di cư chọn lọc**
Chỉ những gì phức tạp
  end note
endif

|Semaines suivantes|
:Triển khai Spring Boot (Cloud Run, EC2);
:Kết nối với PostgreSQL Supabase;
:Triển khai các job được lên lịch đầu tiên;
:Tích hợp APIs bên thứ ba;

stop

note right
**Kiến trúc hybrid cuối cùng**
Supabase + Spring Boot
trong sự hài hòa hoàn hảo
end note
@enduml

Chi phí và Các Cân nhắc Vận hành

Cơ cấu chi phí

@startuml
skinparam backgroundColor #FEFEFE

package "Chi phí hàng tháng ước tính" {

  rectangle "Giai đoạn MVP\n(0-1000 users)" #LightGreen {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot: N/A]
    note bottom: **Tổng cộng: 0€/mois**
  }

  rectangle "Giai đoạn Tăng trưởng\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: **Tổng cộng: 20-80€/mois**
  }

  rectangle "Giai đoạn Mở rộng quy mô\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: **Tổng cộng: 184-414€/mois**
  }
}

note right of "Giai đoạn Mở rộng quy mô\n(10k-100k users)"
Ở giai đoạn này, doanh thu hoàn toàn biện minh cho các chi phí
end note
@enduml

Trách nhiệm vận hành

@startuml
skinparam backgroundColor #FEFEFE

package "Ai Quản Lý Cái Gì?" {

  rectangle "Được quản lý bởi Supabase (0 nỗ lực)" #LightGreen {
    [Authentification]
    [Base de données]
    [Backups automatiques]
    [Scaling automatique]
    [Monitoring DB]
    [Sécurité DB]
  }

  rectangle "Được quản lý bởi GitHub (0 nỗ lực)" #SkyBlue {
    [Hébergement site statique]
    [HTTPS/SSL]
    [CDN global]
    [Déploiement automatique]
  }

  rectangle "Cần quản lý (Spring Boot)" #LightCoral {
    [Déploiement application]
    [Monitoring APM]
    [Logs centralisés]
    [Scaling horizontal]
    [Mises à jour sécurité]
  }
}

note bottom of "Cần quản lý (Spring Boot)"
**Có thể giảm thiểu với:**
• Cloud Run (serverless)
• Kubernetes (nếu cần)
• Dịch vụ được quản lý (RDS, v.v.)
end note
@enduml

Kết luận: Sự cân bằng hoàn hảo

Kiến trúc lai Supabase + Spring Boot không phải là một sự thỏa hiệp, đó là mộtsự hiệp lực.

Các nguyên tắc cần ghi nhớ

@startmindmap
skinparam backgroundColor #FEFEFE
* Architecture\nHybride

** Bắt đầu đơn giản
***_ MVP với Supabase
***_ 0€ chi phí ban đầu
***_Xác nhận nhanh

** Phát triển thông minh
***_ Thêm Spring Boot\nnếu cần
***_ Di chuyển dần
***_ Không có sự thiết kế lại toàn diện

** Sử dụng các lực lượng
***_ Supabase: Đơn giản
***_ Spring Boot: Sức mạnh
***_ PostgreSQL: Nguồn duy nhất

** Giảm thiểu độ phức tạp
***_ Không đồng bộ
***_ Không được sao chép
***Kiến trúc rõ ràng

** Tối ưu hoá chi phí
***_Miễn phí khi bắt đầu
***Mở rộng từng bước
***_ ROI rõ ràng

@endmindmap

Khi nào nên chọn kiến trúc này?

✅ Kiến trúc này là lý tưởng nếu:

  • Bạn muốn khởi động nhanh chóng (MVP trong vài ngày, không phải vài tháng)

  • Bạn dự đoán sự gia tăng độ phức tạp nghiệp vụ

  • Bạn muốn giảm thiểu chi phí ban đầu

  • Bạn thích PostgreSQL và muốn có một nguồn sự thật duy nhất

  • Bạn thích Kotlin và Coroutines cho code nghiệp vụ

  • Bạn muốn tránh hoàn toàn việc bị khóa vào nhà cung cấp

❌ Kiến trúc này KHÔNG phù hợp nếu:

  • Dự án của bạn đơn giản và sẽ luôn như vậy (blog cá nhân → 100% Supabase là đủ)

  • Bạn đã có một stack backend đã được thiết lập mà bạn thành thạo.

  • Bạn thích một monolith truyền thống hơn

  • Bạn cần .NET, Python hoặc một ngôn ngữ backend khác

Tổng quan cuối cùng

@startuml
skinparam backgroundColor #FEFEFE

package "Kiến trúc lai hoàn chỉnh" {

  actor "Người dùng" as users

  rectangle "Frontend (Tĩnh)" #SkyBlue {
    [JBake / GitHub Pages]
    note right: Miễn phí, CDN toàn cầu
  }

  rectangle "Backend đơn giản (Supabase)" #LightGreen {
    [Auth OAuth2]
    [CRUD APIs]
    [Storage]
    [Realtime]
    note right
Miễn phí đến 50k người dùng
Không cần cấu hình máy chủ
    end note
  }

  rectangle "Backend nghiệp vụ (Spring Boot)" #Coral {
    [Orchestration]
    [Jobs Planifiés]
    [Intégrations]
    [Transactions]
    note right
Chỉ bật khi cần thiết
    end note
  }

  database "PostgreSQL\nSource Sự thật duy nhất" 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
**Một cơ sở dữ liệu duy nhất, hai bên tiêu thụ**
• Supabase cho phần đơn giản
• Spring Boot cho phần phức tạp
• Không cần đồng bộ hóa
end note

@enduml

Điều tốt nhất của cả hai thế giới

Kiến trúc này mang lại cho bạn:

🚀 Tốc độ của Supabase

  • Khởi động trong vài giờ, không phải vài tuần

  • Xác thực OAuth2 chỉ trong vài cú nhấp chuột

  • API REST được tạo tự động

  • Không cần cấu hình máy chủ

💪 Sức mạnh của Spring Boot

  • Kotlin và Coroutines cho mã bất đồng bộ thanh lịch

  • Điều phối các quy trình nghiệp vụ phức tạp

  • Các công việc được lên lịch đáng tin cậy

  • Các giao dịch ACID được đảm bảo

  • Hệ sinh thái Spring hoàn chỉnh

💰 Nền kinh tế tiến bộ

  • 0€ để bắt đầu và xác nhận

  • Chi phí đi kèm với tăng trưởng

  • Không thiết kế quá mức sớm

🎯 Tính Linh Hoạt Kiến Trúc

  • Di trú dần dần mà không cần tái cấu trúc

  • Thêm Spring Boot chỉ khi cần thiết

  • Không có tình trạng vendor lock-in hoàn toàn

  • Kiến trúc có thể mở rộng

Để đi xa hơn

Tài nguyên Kỹ thuật

Tài liệu Supabase:

Tài liệu Spring Boot:

Sản phẩm bổ sung:

  • Bảo mật API bằng JWT

  • Tối ưu hóa hiệu năng PostgreSQL

  • Các mẫu di chuyển dần dần

  • Xử lý lỗi trong kiến trúc phân tán

Các trường hợp sử dụng thực tế

Kiến trúc lai này được sử dụng thành công trong:

  • SaaS B2B: Xác thực Supabase, thanh toán Spring Boot

  • Các sàn giao dịch: Danh mục Supabase, giao dịch Spring Boot

  • Nền tảng nội dung: Bài viết Supabase, phân tích Spring Boot

  • Công cụ nội bộ: CRUD Supabase, quy trình làm việc Spring Boot

Danh sách kiểm tra khởi động

Giai đoạn 1 - Nền tảng (Tuần 1)

  • Tạo tài khoản Supabase - [ ] Cấu hình dự án PostgreSQL - [ ] Bật Auth (Google, GitHub) - [ ] Xác định sơ đồ ban đầu - [ ] Cấu hình Row Level Security - [ ] Kiểm thử API từ JBake

Giai đoạn 2 - MVP (Tuần 2-3)

  • Triển khai các trang chính - [ ] Tích hợp xác thực OAuth2 - [ ] Tạo biểu mẫu CRUD - [ ] Cấu hình Storage cho các tệp - [ ] Triển khai trên GitHub Pages - [ ] Thử nghiệm trong điều kiện thực tế

Giai đoạn 3 - Phát triển (Tùy theo nhu cầu)

  • Xác định nhu cầu về logic phức tạp - [ ] Tạo dự án Spring Boot nếu cần thiết - [ ] Cấu hình xác thực JWT Supabase - [ ] Kết nối với PostgreSQL Supabase - [ ] Di chuyển các tính năng phức tạp - [ ] Triển khai các job theo lịch - [ ] Triển khai Spring Boot (Cloud Run, v.v.)

Anti-Patterns cần tránh

❌ Không làm:

  • Sao chép dữ liệu giữa Supabase và Spring Boot

  • Tạo hai cơ sở dữ liệu PostgreSQL riêng biệt

  • Tự lập trình xác thực

  • Sử dụng Spring Boot cho CRUD đơn giản

  • Thiết kế kiến trúc quá mức ngay từ đầu

  • Bỏ qua Row Level Security của Supabase

✅ Thay vào đó hãy làm:

  • Chia sẻ một cơ sở dữ liệu PostgreSQL duy nhất

  • Để Supabase xử lý việc xác thực

  • Chỉ sử dụng Spring Boot cho sự phức tạp

  • Bắt đầu đơn giản, phát triển dần dần

  • Khai thác thế mạnh của từng công nghệ

  • Bảo mật bằng RLS ở cấp cơ sở dữ liệu

Triển vọng phát triển

Thêm các khả năng mới

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Kiến trúc hiện tại" #SkyBlue {
  [JBake]
  [Supabase]
  [Spring Boot]
}

rectangle "Các hướng phát triển khả thi" #LightYellow {

  package "Hiệu năng" {
    [Redis Cache]
    [CDN pour Assets]
    [PostgreSQL Replicas]
  }

  package "Giám sát" {
    [Grafana]
    [Prometheus]
    [Sentry]
  }

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

  package "Các tính năng" {
    [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
**Kiến trúc có thể mở rộng**
Mỗi lần bổ sung đều độc lập
Không cần thiết kế lại toàn bộ
end note
@enduml

Mở rộng theo chiều ngang

Khi ứng dụng của bạn phát triển, kiến trúc lai sẽ mở rộng quy mô một cách tự nhiên:

Supabase :

  • Tự động mở rộng quy mô lên đến hàng triệu thao tác

  • Read replicas cho hiệu năng đọc

  • Khôi phục theo thời điểm để bảo mật

Spring Boot:

  • Nhiều instance phía sau bộ cân bằng tải

  • Thiết kế phi trạng thái tạo điều kiện cho việc mở rộng theo chiều ngang

  • Kubernetes để điều phối nếu cần thiết

PostgreSQL:

  • Phân vùng cho các bảng lớn

  • Gom nhóm kết nối (PgBouncer)

  • Sharding nếu thật sự cần thiết (hiếm)

Chứng tích kiến trúc

Startup SaaS (50k người dùng)

_ Chúng tôi đã khởi đầu với 100% Supabase. Khi đạt 5k người dùng, chúng tôi chỉ thêm Spring Boot cho việc thanh toán Stripe và báo cáo hàng tháng. Một năm sau, 80% hoạt động của chúng tôi vẫn diễn ra qua Supabase. Spring Boot chỉ xử lý phần quan trọng. Việc tách biệt này giúp chúng tôi mở rộng quy mô mà không cần làm lại kiến trúc. _

Nền tảng E-learning (10k người dùng)

_ Xác thực OAuth2 của Supabase đã giúp chúng tôi tiết kiệm 3 tuần phát triển. Các API tự động tạo xử lý toàn bộ danh mục khóa học của chúng tôi. Spring Boot chỉ dùng cho chứng chỉ PDF và email tiến độ. Kiến trúc đơn giản, dễ bảo trì, có thể mở rộng. _

Sàn giao dịch B2B (3k người dùng)

_ Spring Boot xử lý các giao dịch giữa người mua và người bán (quan trọng). Supabase xử lý mọi thứ còn lại: hồ sơ, nhắn tin thời gian thực, tài liệu. Việc chúng dùng chung cùng một cơ sở dữ liệu PostgreSQL giúp chúng ta tránh được mọi việc đồng bộ phức tạp. Lựa chọn kiến trúc tốt nhất mà chúng ta đã thực hiện. _

Tổng hợp: Một mô hình kiến trúc hiện đại

Kiến trúc lai Supabase + Spring Boot đại diện cho một mô hình mới:chuyên môn hóa kiến trúc.

@startuml
skinparam backgroundColor #FEFEFE

rectangle "Mô hình cũ" #LightCoral {
  card "Tất cả trong Backend" {
    [Auth]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [Storage]
    [Realtime]
  }
  note bottom
Độ phức tạp tối đa
ngay từ ngày 1
  end note
}

rectangle "Mô hình mới" #LightGreen {
  card "Supabase\n(Commodité)" {
    [Auth]
    [CRUD Simple]
    [Storage]
    [Realtime]
  }

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

  note bottom
Độ phức tạp tăng dần
chỉ được thêm vào khi thật sự cần thiết
  end note
}

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

@enduml

Nguyên tắc cơ bản:Đừng xây dựng những gì đã tồn tại dưới dạng dịch vụ. Hãy tập trung vào những gì tạo nên sự khác biệt cho ứng dụng của bạn.

Quy tắc 80/20

Trong hầu hết các ứng dụng:

  • 80% các hoạt độnglà CRUD tiêu chuẩn → Supabase

  • 20% các hoạt độngcần logic nghiệp vụ → Spring Boot

Quy tắc tự nhiên này biện minh cho kiến trúc lai.

@startuml
skinparam backgroundColor #FEFEFE

package "Phân phối Hoạt động" {

  rectangle "80% - Hoạt động Tiêu chuẩn" #LightGreen {
    [Lecture de données]
    [Création d'entités]
    [Mise à jour simple]
    [Suppression]
    [Upload fichiers]
    [Authentification]

    note bottom: **Được quản lý bởi Supabase**
  }

  rectangle "20% - Logic Nghiệp vụ" #Coral {
    [Calculs complexes]
    [Workflows multi-étapes]
    [Transactions critiques]
    [Intégrations tierces]
    [Jobs planifiés]

    note bottom: **Được quản lý bởi Spring Boot**
  }
}

note right
**Trọng tâm tối ưu:**
Thời gian phát triển của bạn
được tập trung vào 20% yếu tố
tạo nên sự khác biệt cho sản phẩm của bạn
end note
@enduml

Kết luận cuối cùng

Kiến trúc lai không phải là một thỏa hiệp kỹ thuật, mà là mộtquyết định chiến lược.

Nó cho phép bạn:

  • ✅ Bắt đầu nhanh với một MVP hoạt động được

  • ✅ Xác thực thị trường của bạn mà không cần đầu tư lớn

  • ✅ Tiến triển dần dần khi độ phức tạp đòi hỏi

  • ✅ Kiểm soát chi phí của bạn ở từng bước

  • ✅ Khai thác điều tốt nhất từ mỗi công nghệ

  • ✅ Tránh việc kỹ thuật hóa quá mức quá sớm

  • ✅ Duy trì tính linh hoạt cho tương lai

Cô ấy đại diện cho:

  • 🎯Chủ nghĩa thực dụng: Mỗi công nghệ mà cô ấy thành thạo

  • 🚀Vận tốc: Thời gian đưa sản phẩm ra thị trường tối thiểu

  • 💰Kinh tế: Chi phí phù hợp với giá trị

  • 🔮Khả năng mở rộng: Kiến trúc phát triển cùng bạn

  • 🛡️Độ bền vững: Các dịch vụ đã được kiểm chứng và đáng tin cậy

Bước Tiếp Theo Của Bạn

Nếu kiến trúc này có ý nghĩa với bạn, đây là nơi để bắt đầu:

  1. Tạo một tài khoản Supabase(miễn phí)

  2. Hãy xác định lược đồ dữ liệu tối thiểu của bạn

  3. Cấu hình xác thực OAuth2

  4. Tạo trang JBake đầu tiên của bạn sử dụng API

  5. Triển khai trên GitHub Pages

Bạn sẽ có một MVP hoạt động trongvài ngày.

Spring Boot sẽ đến một cách tự nhiên khi bạn cần nó. Không phải trước đó.


Kiến trúc lai là nghệ thuật xây dựng chính xác những gì cần thiết, vào đúng thời điểm.

Chúc bạn phát triển tốt! 🚀


Hãy chia sẻ bài viết này nếu bạn nghĩ nó có thể giúp các nhà phát triển khác đưa ra những lựa chọn kiến trúc đúng đắn.

Bài viết liên quan