Kiến trúc lai : Tốt nhất của cả hai thế giới với Supabase và Spring Boot
Đăng ngày 14 January 2026
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ệ.
- Ngụy biện lưỡng nan của Kiến trúc Hiện đại
- Tầm nhìn kiến trúc
- Nguyên tắc thiết kế
- Điều phối các Luồng
- Ma trận Quyết định
- Ví dụ về Kiến trúc theo Loại Dự án
- Chiến lược di cư dần dần
- Chi phí và Các Cân nhắc Vận hành
- Kết luận: Sự cân bằng hoàn hảo
- Để đi xa hơn
- Triển vọng phát triển
- Chứng tích kiến trúc
- Tổng hợp: Một mô hình kiến trúc hiện đại
- Kết luận cuối cùng
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:
-
Tạo một tài khoản Supabase(miễn phí)
-
Hãy xác định lược đồ dữ liệu tối thiểu của bạn
-
Cấu hình xác thực OAuth2
-
Tạo trang JBake đầu tiên của bạn sử dụng API
-
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.