Báo cáo kiến trúc và bài toán khó trong microservices
Ngày viết: 30/05/2026 Phạm vi: microservices như một phong cách kiến trúc cho hệ thống lớn: service boundary, bounded context, independent deployability, database per service, distributed transactions, saga, outbox, event-driven architecture, API gateway, BFF, service mesh, observability, testing, release, security, platform, team ownership, migration từ monolith và khi nào không nên dùng microservices. Không bàn phần cơ bản như "microservice là service nhỏ", "dùng Docker/Kubernetes", hay "tạo nhiều repo cho hiện đại".
1. Tóm tắt thẳng
Microservices không khó vì có nhiều service.
Nó khó vì:
boundary sai thì mọi thứ đắt hơn,
data ownership sai thì consistency đau hơn,
API contract sai thì team phụ thuộc nhau hơn,
event sai thì sự thật phân mảnh hơn,
observability thiếu thì debugging khó hơn,
deployment độc lập trên giấy nhưng release vẫn phải họp cả công ty,
và nếu team ownership chưa đủ trưởng thành, microservices chỉ biến monolith thành distributed monolith.
Một monolith rối có thể khó sửa.
Một microservices rối có thể:
- khó sửa hơn vì lỗi chạy qua nhiều network hop,
- khó deploy hơn vì dependency matrix,
- khó test hơn vì environment phức tạp,
- khó debug hơn vì request đi qua nhiều service,
- khó bảo mật hơn vì nhiều API/internal traffic,
- khó đảm bảo data consistency hơn vì nhiều database,
- khó hiểu hơn vì logic nghiệp vụ bị chia nhỏ,
- khó vận hành hơn vì nhiều on-call/alert/dashboard,
- khó thay đổi hơn vì contract giữa team không rõ.
Câu senior phải giữ trong đầu:
Microservices không phải mục tiêu.
Microservices là cái giá ta trả để đổi lấy independent delivery,
ownership rõ, blast radius nhỏ hơn và khả năng scale/evolve từng capability.
Nếu không lấy được các lợi ích đó, ta chỉ đang mua thêm complexity.
Một hệ microservices production phải trả lời được:
- service boundary dựa trên business capability hay theo bảng dữ liệu?
- service có independently deployable thật không?
- mỗi service sở hữu dữ liệu nào?
- service khác có đọc database của nó không?
- API/event contract versioning thế nào?
- thay đổi schema có phá consumer không?
- transaction xuyên service xử lý bằng saga, orchestration, compensation hay tránh luôn?
- update DB và publish event có atomic không?
- request trace được qua các service không?
- nếu service A timeout, service B retry thế nào?
- service mesh/API gateway giải quyết vấn đề thật nào?
- test strategy là gì: unit, contract, component, integration, E2E?
- ai on-call cho service?
- team có quyền deploy/rollback độc lập không?
- nếu service tăng từ 10 lên 200, platform có chịu nổi không?
- khi nào nên gộp service lại?
Điểm quan trọng:
Microservices thành công khi boundary, data, deployment và team ownership cùng đúng.
Chỉ tách code mà không tách ownership và data thì chưa phải microservices trưởng thành.
2. Cách nghiên cứu
Báo cáo này tổng hợp từ các nguồn chính:
- Martin Fowler/James Lewis về microservices, distributed objects và microservice prerequisites.[^fowler-microservices][^fowler-distributed][^fowler-prerequisites]
- CNCF Cloud Native Glossary về microservices architecture và service mesh trong cloud-native ecosystem.[^cncf-microservices][^cncf-service-mesh]
- Chris Richardson/Microservices.io về pattern language: database per service, saga, transactional outbox, API gateway, service discovery.[^microservices-patterns][^database-per-service][^saga][^transactional-outbox][^api-gateway-pattern]
- AWS Prescriptive/whitepaper guidance về microservices patterns: API-driven, event-driven, data streaming.[^aws-microservices]
- Thoughtworks về microservices như evolutionary architecture và cảnh báo legacy/fit context.[^tw-microservices][^tw-evolutionary]
- Sam Newman về Backends for Frontends và tư duy service độc lập theo domain.[^sam-bff][^sam-site]
- OpenAPI và AsyncAPI cho contract của synchronous/asynchronous APIs.[^openapi][^asyncapi]
- OpenTelemetry cho distributed tracing/metrics/logs trong hệ phân tán.[^opentelemetry]
- Istio/CNCF/SPIFFE cho service mesh, traffic, security, workload identity.[^istio][^spiffe]
- DORA, Google SRE, Team Topologies, SLSA/NIST SSDF cho delivery performance, reliability, team ownership và supply chain security.[^dora-2024][^sre-slo][^team-topologies][^slsa][^nist-ssdf]
Cách đọc báo cáo:
- Nếu đang ở monolith: đọc kỹ phần "khi nào chưa nên tách" và migration/strangler.
- Nếu đã có vài service: đọc phần boundary, data ownership, outbox, contract, observability.
- Nếu đã có nhiều service: đọc phần platform, service mesh, testing, governance, team ownership.
- Nếu đang quản lý team: đọc phần socio-technical và DORA/ownership.
3. Microservices là gì, nói chính xác hơn
Một định nghĩa thực dụng:
Microservice là một service independently deployable,
được thiết kế quanh business capability hoặc bounded context,
sở hữu dữ liệu/lifecycle của mình,
và giao tiếp với service khác qua contract rõ.
Không phải microservice nếu:
- chỉ là một controller nhỏ,
- chỉ là một repo riêng,
- chỉ là một container,
- chỉ là một CRUD service theo bảng,
- deploy riêng nhưng database shared lung tung,
- deploy riêng nhưng release vẫn cần coordinate với 10 service khác,
- service không có owner/on-call,
- logic nghiệp vụ chính nằm ở orchestration layer trung tâm.
CNCF mô tả microservices như một architecture pattern thường đối lập với monolith và giúp deploy/update/scale từng phần độc lập hơn, nhưng cũng tạo overhead vận hành lớn hơn.[^cncf-microservices]
Martin Fowler/James Lewis nhấn mạnh microservices là một architectural style gồm các services nhỏ, chạy trong process riêng, giao tiếp qua cơ chế nhẹ và có thể deploy độc lập.[^fowler-microservices]
Nhưng định nghĩa quan trọng nhất với production là:
independently deployable + business/domain boundary + data ownership.
Nếu thiếu một trong ba, rất dễ thành distributed monolith.
4. Microservices giải quyết bài toán gì?
Microservices có thể giúp khi:
- nhiều team cần ship độc lập,
- domain có nhiều bounded context rõ,
- các capability có tốc độ thay đổi khác nhau,
- workload scale khác nhau,
- risk/blast radius cần tách,
- compliance/security boundary khác nhau,
- technology/runtime khác nhau có lý do thật,
- business cần deploy một phần mà không release toàn hệ.
Ví dụ:
Search cần index/ranking riêng.
Payment cần ledger/reconciliation riêng.
Media cần encoding/CDN workflow riêng.
IAM cần policy/audit riêng.
Notification cần throughput/retry/fanout riêng.
Microservices không giải quyết tốt nếu vấn đề thật là:
- domain chưa hiểu,
- team chưa có DevOps/on-call,
- testing yếu,
- CI/CD yếu,
- data model rối,
- ownership mơ hồ,
- observability nghèo,
- monolith chưa có module boundary.
Trong những trường hợp đó, microservices sẽ phóng đại vấn đề.
5. Khi nào không nên dùng microservices
Không nên microservices sớm khi:
- team nhỏ, ít hơn 2-3 stream-aligned teams,
- domain còn đổi liên tục và chưa hiểu boundary,
- monolith chưa quá đau về delivery,
- chưa có CI/CD đáng tin,
- chưa có observability/tracing,
- chưa có on-call/incident process,
- database vẫn là shared source of truth,
- business chưa cần deploy độc lập,
- performance bottleneck chưa được đo,
- service split chủ yếu vì "cho giống Big Tech".
Martin Fowler có bài riêng về prerequisites trước khi dùng microservices, trong đó nhấn mạnh rapid provisioning, monitoring và rapid application deployment là nền quan trọng.[^fowler-prerequisites]
Nói thẳng:
Nếu chưa vận hành nổi một monolith tử tế,
khả năng cao chưa vận hành nổi 30 microservices.
Lựa chọn thực dụng hơn nhiều khi bắt đầu:
modular monolith,
explicit module boundaries,
internal events/outbox,
clear domain contexts,
API-first inside the monolith,
separate deploy only khi boundary và ownership đã chứng minh.
6. Modular monolith là bước đệm rất đáng tôn trọng
Modular monolith không phải thất bại.
Nó là cách:
- giữ deployment đơn giản,
- giữ transaction local,
- giữ debugging dễ,
- nhưng vẫn ép domain/module boundary rõ.
Một modular monolith tốt có:
- modules theo bounded context,
- public interface rõ,
- không query trực tiếp module data lung tung,
- domain events nội bộ,
- dependency rules,
- tests theo module,
- ownership theo module nếu team đủ lớn,
- khả năng tách service sau này.
Bẫy:
- gọi là modular nhưng module nào cũng import module nào,
- shared models quá nhiều,
- database schema lẫn,
- business rule nằm trong helper chung,
- không có dependency checks,
- không có event/outbox discipline.
Pattern:
Modular monolith before microservices.
Service extraction after domain and team boundaries stabilize.
7. Service boundary: tách theo bảng là bẫy kinh điển
Boundary tốt thường theo:
- business capability,
- bounded context,
- lifecycle/invariant,
- data ownership,
- team ownership,
- change cadence,
- compliance/risk boundary,
- scalability profile.
Boundary xấu thường theo:
- database table,
- CRUD noun,
- technical layer,
- UI page,
- "service phải nhỏ",
- team tạm thời,
- framework/library.
Ví dụ boundary xấu:
UserService
OrderService
PaymentService
CourseService
StatusService
ReportService
Không phải tên xấu, nhưng nếu chỉ dựa trên nouns/tables thì thiếu domain.
Boundary tốt hơn cần hỏi:
Context này có language riêng không?
Nó có invariants riêng không?
Nó có data riêng không?
Nó có release cadence riêng không?
Team nào chịu trách nhiệm end-to-end?
DDD bounded context giúp tìm boundary nơi một model/language nhất quán.[^fowler-bounded-context]
Microservice nên là physical deployment của boundary đã hiểu, không phải công cụ để tìm boundary bằng đau khổ production.
8. Team ownership: microservice là socio-technical boundary
Microservices không chỉ là technical design.
Nó là organizational design.
Team Topologies nhấn mạnh team cognitive load và interaction modes.[^team-topologies]
Microservice nên có:
- owning team,
- clear mission,
- service catalog entry,
- API/event contracts,
- on-call,
- dashboards,
- SLO,
- runbook,
- cost ownership,
- security ownership,
- roadmap.
Bẫy:
- một team sở hữu 40 services,
- service không có owner,
- platform team phải approve mọi deploy,
- teams phụ thuộc nhau qua Slack,
- API thay đổi cần họp nhiều team,
- on-call nhận alert nhưng không có quyền sửa.
Rule:
Nếu service không có owner đủ quyền vận hành,
đó không phải service boundary tốt.
9. Independent deployability: phép thử thật
Chris Richardson nhấn mạnh independently deployable là đặc tính cốt lõi của microservice architecture.[^independent-deployability]
Một service independently deployable khi:
- build/test/release riêng,
- deploy không cần lockstep với service khác,
- contract backward-compatible,
- database migration không phá consumers,
- config/feature flags riêng,
- rollback được,
- observability đủ để xác minh,
- team có quyền release.
Không independently deployable nếu:
- phải deploy frontend/API/service/db cùng lúc,
- shared library đổi là 20 services phải redeploy,
- event schema breaking change không version,
- test E2E toàn hệ là gate duy nhất,
- database shared khiến schema change block nhiều team,
- release calendar chung toàn công ty.
Phép thử:
Service A có thể deploy phiên bản mới lúc 14:00
mà service B/C không biết và không cần release không?
Nếu không, hãy gọi nó là distributed module trước khi gọi là microservice.
10. Database per service: khó nhưng là trọng tâm
Microservices.io xem Database per Service là pattern quan trọng: mỗi service giữ database riêng tư và không service nào truy cập trực tiếp database của service khác.[^database-per-service]
Lý do:
- bảo vệ data ownership,
- giảm coupling qua schema,
- cho phép deploy/schema evolution độc lập,
- giữ domain invariants trong service owner.
Nhược điểm:
- query xuyên service khó,
- transaction xuyên service khó,
- reporting cần data platform/read models,
- duplication/denormalization,
- eventual consistency,
- migration phức tạp.
Bẫy lớn:
Service A có database riêng, nhưng Service B query thẳng vào database A để report.
Đây là boundary giả.
Pattern:
Private database.
Public API/events.
Read models/materialized views cho query.
Data contracts cho downstream.
Reconciliation cho critical flows.
11. Distributed transactions: tránh trước, saga sau, 2PC rất cẩn thận
Khi mỗi service sở hữu database riêng, transaction local không bao hết workflow.
Ví dụ checkout:
Order -> Payment -> Inventory -> Fulfillment -> Notification
Không nên mặc định dùng distributed transaction/2PC.
Lý do:
- coupling runtime cao,
- availability thấp hơn,
- lock/coordination khó,
- không hợp nhiều external systems,
- rollback side effects ngoài DB khó.
Saga pattern chia workflow thành chuỗi local transactions và compensation khi cần.[^saga]
Có hai kiểu:
- choreography: services react to events.
- orchestration: process manager/workflow điều phối.
Bẫy:
- compensation không thật sự đảo được side effect,
- event mất/trùng,
- saga không có state machine rõ,
- choreography thành flow khó hiểu,
- orchestration thành god service,
- user thấy trạng thái trung gian không được thiết kế.
Rule:
Nếu invariant cần atomic mạnh, xem lại boundary.
Nếu workflow dài, model saga/process explicitly.
Nếu side effect không đảo được, cần hold/reserve/confirm pattern.
12. Transactional outbox: pattern gần như bắt buộc
Bài toán dual write:
Ghi database thành công.
Publish message thất bại.
Hoặc:
Publish message thành công.
Ghi database rollback.
Transactional outbox giải bằng cách ghi event/outbox record trong cùng transaction với domain state, rồi publish async từ outbox.[^transactional-outbox]
Debezium Outbox Event Router là một implementation pattern phổ biến dùng CDC để publish event từ outbox table.[^debezium-outbox]
Pattern:
BEGIN
update domain state
insert outbox event
COMMIT
publisher/CDC reads outbox -> broker
consumer handles idempotently
Bẫy:
- consumer không idempotent,
- outbox event thiếu aggregate/version,
- publish order không rõ,
- outbox table không cleanup,
- replay tạo side effect,
- event schema không versioned,
- outbox được dùng cho mọi log vặt.
Outbox không làm hệ "exactly once".
Nó làm hệ có đường đi đáng tin hơn khi update DB và publish event.
13. Event-driven architecture: event là contract, không phải log
Event tốt là sự kiện domain đã xảy ra:
OrderPlaced
PaymentAuthorized
EnrollmentGranted
CourseCompleted
RefundIssued
Event không tốt:
OrderUpdated
StatusChanged
DataChanged
ThingHappened
Event contract cần:
- name,
- producer owner,
- schema,
- semantic meaning,
- version,
- aggregate/entity ID,
- event time,
- causation/correlation ID,
- idempotency key,
- privacy classification,
- retention,
- consumers.
AsyncAPI giúp mô tả asynchronous/event-driven APIs bằng machine-readable specification.[^asyncapi]
Bẫy:
- event là bản dump database row,
- event dùng thuật ngữ ambiguous,
- event không biết source of truth,
- breaking schema change,
- consumer tự diễn giải khác nhau,
- event không có owner,
- topic thành integration garbage.
Rule:
Event is a public contract.
Treat it like API, not like internal log line.
14. API contracts: REST/gRPC/message đều cần versioning
Microservices sống bằng contracts.
Contract gồm:
- endpoint/message,
- schema,
- semantics,
- auth,
- rate limits,
- errors,
- idempotency,
- pagination,
- backwards compatibility,
- deprecation.
OpenAPI là specification phổ biến để mô tả HTTP APIs.[^openapi]
Bẫy:
- chỉ version URL nhưng đổi semantics,
- remove field consumer đang dùng,
- error codes inconsistent,
- timeout behavior không rõ,
- idempotency không document,
- API gateway che mất owner thật,
- internal API không có contract vì "nội bộ thôi".
Pattern:
Consumer-driven contract tests where useful.
Backward-compatible changes by default.
Deprecation windows.
Schema compatibility checks.
API ownership in catalog.
Internal API vẫn là API production.
15. Synchronous calls: remote call không phải function call
Microservices làm network thành part of business logic.
Remote call có:
- latency,
- timeout,
- partial failure,
- retry,
- rate limit,
- auth,
- serialization,
- versioning,
- observability.
Bẫy:
- call chain quá dài,
- timeout mặc định quá lâu,
- retry không jitter,
- retry side effect không idempotent,
- N+1 cross-service calls,
- service A availability nhân với service B/C/D,
- gateway aggregation thành bottleneck,
- "shared internal client" làm coupling chặt.
Pattern:
Explicit timeout budgets.
Circuit breakers where meaningful.
Bulkheads.
Backpressure.
Idempotent commands.
Avoid synchronous chains for long workflows.
Use async/read models for high fanout.
Fowler nhắc lại "First Law of Distributed Objects": đừng quên distributed boundary có chi phí thật.[^fowler-distributed]
16. API Gateway và BFF: cổng không nên thành god service
API Gateway pattern cung cấp unified entry point cho clients tới microservices.[^api-gateway-pattern]
Gateway thường xử lý:
- routing,
- authn/authz edge,
- rate limit,
- request shaping,
- protocol translation,
- observability,
- WAF/bot protection,
- response aggregation nhẹ.
BFF pattern của Sam Newman tách backend theo từng frontend/client need.[^sam-bff]
Bẫy:
- gateway chứa business logic,
- gateway aggregate quá nhiều service realtime,
- gateway team thành bottleneck,
- BFF duplicate logic domain,
- auth chỉ check ở gateway, service internal trust mù,
- gateway hides downstream failures poorly.
Rule:
Gateway/BFF nên tối ưu client boundary.
Domain authority vẫn thuộc domain services.
17. Service discovery, load balancing và runtime coupling
Trong microservices, service instances thay đổi liên tục.
Cần:
- service registry/discovery,
- load balancing,
- health checks,
- readiness/liveness,
- retries/timeouts,
- circuit breaking,
- traffic shifting,
- locality/zone awareness.
Bẫy:
- health check chỉ trả 200 nhưng dependency chết,
- readiness không tách liveness,
- load balancer gửi traffic tới instance đang warm up,
- zone failover tạo overload region khác,
- client-side library versions khác nhau,
- service discovery cache stale.
Pattern:
Define health semantics.
Separate liveness, readiness, startup.
Use traffic policies consciously.
Monitor from caller and callee perspective.
18. Service mesh: dùng khi vấn đề thật đủ lớn
CNCF mô tả service mesh như dedicated infrastructure layer để quản lý service-to-service communication, thường thêm reliability, observability và security capabilities.[^cncf-service-mesh]
Istio tách control plane và data plane, cung cấp traffic management, observability và security capabilities.[^istio]
Service mesh có thể giúp:
- mTLS,
- service identity,
- traffic routing,
- retries/timeouts,
- circuit breaking,
- telemetry,
- policy,
- progressive delivery,
- zero-trust direction.
Nhưng mesh cũng thêm:
- operational complexity,
- latency/overhead,
- config complexity,
- sidecar/ambient mode tradeoffs,
- debugging layer mới,
- platform team burden,
- failure mode mới.
Bẫy:
- dùng mesh để che app không có timeout/idempotency,
- config mesh phức tạp hơn app,
- mTLS bật nhưng authorization yếu,
- retry policy mesh tạo storm,
- telemetry mesh làm tưởng đã có observability đủ.
Rule:
Service mesh tốt khi platform maturity đủ và service count/risk đủ lớn.
Không dùng mesh để thay design discipline.
19. Observability: microservices không trace được là mù
Microservices cần observability mặc định:
- distributed traces,
- structured logs,
- metrics,
- correlation ID,
- causation ID,
- dependency maps,
- service ownership,
- SLOs,
- deploy markers,
- business events.
OpenTelemetry cung cấp vendor-neutral framework cho traces, metrics và logs.[^opentelemetry]
Bẫy:
- log mỗi service không join được,
- trace không propagate qua queue,
- async workflows mất causation,
- metrics không có tenant/region/service dimension hợp lý,
- high cardinality nổ cost,
- dashboard theo service nhưng incident theo user flow,
- alert không route đúng owner.
Pattern:
Trace by user journey, not only by service.
Correlate sync and async.
Emit domain events for critical states.
Every service has owner, dashboard, SLO, runbook.
20. Testing strategy: E2E không thể gánh hết
Microservices tăng testing complexity.
Các lớp test:
- unit tests,
- domain/model tests,
- component tests,
- contract tests,
- integration tests,
- consumer-driven contract tests,
- E2E tests,
- synthetic production tests,
- chaos/resilience tests.
Bẫy:
- E2E toàn hệ là gate chính,
- test environment không giống production,
- contract không test,
- mocks không match provider,
- flaky tests quá nhiều,
- mỗi PR cần spin toàn hệ,
- migration chỉ test happy path.
Pattern:
Test pyramid shifts toward component + contract tests.
E2E covers few critical journeys.
Production synthetic probes validate real dependencies.
Nếu deploy một service cần test toàn bộ công ty, independent deployability chưa đạt.
21. Deployment và release: deploy độc lập không đồng nghĩa release độc lập
Một service có thể deploy riêng nhưng feature release vẫn phụ thuộc:
- API contract,
- data migration,
- UI changes,
- feature flags,
- downstream readiness,
- event consumers,
- policy changes,
- documentation/support.
Pattern:
- expand/contract schema migration,
- backward-compatible API changes,
- feature flags,
- dark launch,
- canary,
- blue/green,
- progressive delivery,
- rollback,
- deployment markers.
Bẫy:
- deploy breaking contract,
- rollback code nhưng không rollback schema,
- feature flag permanent,
- canary chỉ đo CPU,
- release train toàn hệ vì contract yếu,
- deployment order manual wiki.
Rule:
Deploy là thao tác kỹ thuật, nên nhỏ và thường xuyên.
Release là quyết định sản phẩm, nên được kiểm soát và an toàn.
22. Security: zero trust giữa service không tự có
Microservices tăng attack surface:
- nhiều APIs,
- nhiều service identities,
- nhiều secrets,
- nhiều network paths,
- nhiều dependencies,
- nhiều container images,
- nhiều CI/CD pipelines.
Cần:
- service identity,
- mTLS khi phù hợp,
- least privilege,
- authz ở service boundary,
- secrets rotation,
- workload identity,
- API scopes,
- audit,
- supply chain security,
- vulnerability management.
SPIFFE định nghĩa framework/standards cho workload identity giữa application services.[^spiffe]
SLSA và NIST SSDF giúp kiểm soát supply chain/secure SDLC.[^slsa][^nist-ssdf]
Bẫy:
- internal network trusted mặc định,
- auth chỉ ở gateway,
- shared service token,
- secrets trong env/logs,
- service account quá quyền,
- image unsigned vẫn deploy,
- dependency CVE không map service owner.
Pattern:
Every service call has caller identity.
Every sensitive action checks authorization.
Every artifact has provenance.
Every service has least-privilege runtime identity.
23. Data queries và reporting: không query xuyên database
Microservices làm operational data phân tán.
Business vẫn cần:
- dashboard,
- search,
- reports,
- customer support views,
- audit,
- ML/analytics.
Bẫy:
- BI query thẳng service databases,
- support tool join nhiều prod DB,
- search index không có ACL,
- read model không có owner,
- data lake không có lineage,
- report dùng eventual data nhưng không nói freshness.
Pattern:
- event-driven read models,
- CQRS khi phù hợp,
- data warehouse/lakehouse,
- data contracts,
- CDC/outbox,
- permission-aware projections,
- freshness SLO,
- reconciliation.
Microservices cần data platform hơn monolith.
Vì dữ liệu không còn nằm trong một database dễ query.
24. Versioning và compatibility: breaking change là organizational event
Trong microservices, breaking change không chỉ là code change.
Nó là coordination event.
Versioning cần cho:
- REST/gRPC APIs,
- events,
- database schemas,
- config,
- feature flags,
- SDKs,
- policy rules,
- workflows.
Bẫy:
v2nhưng semantics vẫn đổi ngầm,- old clients không sunset,
- event consumer không biết producer đổi,
- shared DTO library version drift,
- protobuf field reuse,
- enum thêm value làm consumer fail,
- deprecation không có owner.
Pattern:
Prefer additive changes.
Consumer tolerance.
Schema compatibility checks.
Deprecation windows.
Usage tracking before removal.
Version policy in service catalog.
25. Granularity: service nhỏ quá cũng là lỗi
Service quá lớn:
- nhiều owner,
- nhiều reasons to change,
- deploy chậm,
- blast radius lớn.
Service quá nhỏ:
- nhiều runtime dependencies,
- chatty calls,
- domain logic phân mảnh,
- operational overhead,
- testing phức tạp,
- team ownership mỏng.
Không có kích thước chuẩn.
Hỏi:
- service có business capability rõ không?
- service có sở hữu invariants không?
- service có deploy độc lập không?
- service có dữ liệu riêng không?
- team có vận hành nổi không?
- call graph có hợp lý không?
Rule:
Microservice đủ nhỏ để một team hiểu và deploy độc lập,
đủ lớn để chứa một domain responsibility có ý nghĩa.
26. Platform requirement: microservices cần nền vận hành mạnh
Microservices production cần platform:
- service catalog,
- CI/CD,
- artifact registry,
- environment management,
- secrets,
- config,
- service discovery,
- observability,
- policy,
- incident management,
- cost allocation,
- security scanning,
- templates/golden paths.
Bẫy:
- mỗi team tự chọn logging/tracing/deploy style,
- service catalog không có,
- không biết service nào gọi service nào,
- CI/CD copy-paste,
- secrets/process drift,
- on-call không map service,
- cost không chia được.
Pattern:
Golden path for service creation.
Default observability.
Default security.
Default deployment.
Escape hatch with ownership.
Developer platform báo cáo trước đã nói: platform tốt là leverage, platform tệ là bureaucracy.
Microservices làm nhu cầu platform xuất hiện sớm hơn và mạnh hơn.
27. Cost: microservices có giá kinh tế thật
Microservices tăng cost:
- compute overhead,
- network calls,
- telemetry volume,
- CI/CD minutes,
- test environments,
- platform team,
- service mesh overhead,
- operational toil,
- incident coordination,
- duplicated libraries/runtime.
Nhưng có thể giảm cost nếu:
- scale từng capability riêng,
- isolate noisy workload,
- optimize hot services,
- reduce release coordination,
- reduce failure blast radius.
Bẫy:
- tách service nhưng workload scale giống nhau,
- mỗi service có database riêng quá đắt,
- logs/traces tăng theo service count,
- platform overhead vượt business value,
- không đo cost per service/capability.
Rule:
Microservice phải trả được tiền thuê nhà của nó:
delivery independence, scaling independence, risk isolation hoặc domain clarity.
28. Migration từ monolith: strangler, không big bang
Migration tốt thường theo:
hiểu hệ thống -> module hóa -> chọn điểm tách -> chuyển traffic
-> đồng bộ dữ liệu -> chạy song song -> chuyển hẳn -> gỡ đường cũ.
Strangler Fig pattern là cách dần thay thế hệ cũ bằng cách xây hệ mới quanh nó và chuyển dần flow.[^fowler-strangler]
Bẫy:
- rewrite toàn bộ,
- tách service nhưng database vẫn shared không kế hoạch,
- dual-write không reconcile,
- service mới phụ thuộc monolith theo hidden calls,
- monolith vẫn là source of truth nhưng service nghĩ mình own data,
- không có rollback,
- không có business slice nhỏ để chứng minh.
Pattern:
- bắt đầu từ điểm tách rủi ro thấp nhưng có giá trị cao,
- anti-corruption layer,
- database view/wrapping khi cần tạm thời,
- outbox/CDC,
- shadow reads,
- chuyển đổi từng bước,
- metrics/evidence,
- decommission plan.
Migration microservices là business change, không chỉ refactor code.
29. Distributed monolith: dấu hiệu nhận biết
Dấu hiệu:
- service nào đổi cũng phải deploy service khác,
- database shared,
- sync call chain dài,
- business transaction yêu cầu lockstep,
- E2E test toàn hệ là gate chính,
- service không có owner,
- một "orchestrator" trung tâm chứa logic mọi domain,
- API breaking changes thường xuyên,
- deploy phải theo thứ tự wiki,
- observability không trace được,
- outage một service kéo sập toàn hệ.
Nguyên nhân:
- boundary sai,
- data ownership sai,
- team ownership sai,
- platform yếu,
- migration nửa vời,
- dùng microservices để né modularity discipline.
Thuốc:
- review bounded contexts,
- tách data ownership,
- contract versioning,
- reduce synchronous coupling,
- outbox/events/read models,
- service ownership,
- platform golden paths,
- maybe merge services back.
Gộp service lại không phải thất bại.
Đôi khi đó là kiến trúc trưởng thành.
30. Microservices và global-scale
Global microservices thêm nhiều chiều:
- region-aware routing,
- data residency,
- per-region deployment,
- cross-region events,
- schema rollout waves,
- service discovery global,
- regional failover,
- latency between services,
- split-brain risk,
- tenant/cell placement,
- observability by region.
Bẫy:
- service A active-active, service B single-region,
- cross-region sync calls,
- event replication không idempotent,
- residency bị phá bởi logs/events,
- failover không biết downstream region,
- release global cùng lúc gây blast radius lớn.
Pattern:
Prefer regional autonomy for critical paths.
Keep synchronous calls within region where possible.
Use cells/tenants to limit blast radius.
Roll out service changes by region/cell.
Microservices không tự làm global easier.
Nó chỉ cho nhiều knobs hơn; knobs nhiều hơn cũng dễ vặn sai hơn.
31. Architecture review checklist cho microservices
Motivation
- Vì sao cần microservices?
- Vấn đề là delivery, scale, ownership, compliance hay team?
- Modular monolith có đủ chưa?
- Lợi ích có lớn hơn complexity không?
Boundary
- Service theo business capability/bounded context chưa?
- Có data ownership riêng không?
- Có invariants riêng không?
- Boundary có khớp team ownership không?
- Có service quá nhỏ/quá kỹ thuật không?
Data
- Service khác có query DB trực tiếp không?
- Transaction xuyên service xử lý thế nào?
- Outbox/inbox/idempotency có không?
- Read models/reporting/search lấy dữ liệu thế nào?
- Reconciliation cho critical flows có không?
Contracts
- API/event contract có owner/version không?
- Backward compatibility policy là gì?
- Consumer-driven contract tests có cần không?
- Deprecation và usage tracking có không?
Runtime
- Timeout/retry/circuit breaker chuẩn chưa?
- Call graph có quá sâu không?
- Service discovery/load balancing/health checks rõ không?
- Failure domain và blast radius là gì?
Observability
- Trace qua sync và async có không?
- Logs structured/correlation ID có không?
- SLO per service và per user journey có không?
- Alert route đúng team không?
Delivery
- Service có deploy độc lập thật không?
- Build once/promote many không?
- Rollback và schema migration an toàn không?
- Release có feature flags/canary không?
Security
- Service identity có không?
- Internal calls có authn/authz không?
- Secrets/credentials rotate được không?
- Artifact provenance/signing có không?
- Least privilege runtime có không?
Organization
- Team nào own service?
- Team có đủ capacity on-call không?
- Platform support có đủ không?
- Service catalog có đúng không?
- Cognitive load có vượt sức team không?
32. Mô hình tư duy riêng: S-E-R-V-I-C-E-S
Để không bỏ sót khi nghĩ về microservices, dùng mô hình:
S - Service boundary
E - Evolution path
R - Runtime coupling
V - Versioned contracts
I - Independent deployability
C - Consistency and data ownership
E - Evidence and observability
S - Socio-technical ownership and security
S - Service boundary
Câu hỏi:
- service đại diện capability nào?
- bounded context nào?
- invariant nào?
- dữ liệu nào?
- boundary này giảm hay tăng coordination?
E - Evolution path
Câu hỏi:
- từ monolith tách ra thế nào?
- có strangler/anti-corruption không?
- migration data ra sao?
- nếu tách sai, merge lại thế nào?
- deprecation thế nào?
R - Runtime coupling
Câu hỏi:
- call graph sâu không?
- sync hay async?
- timeout/retry/backpressure?
- service nào là critical dependency?
- failure lan như thế nào?
V - Versioned contracts
Câu hỏi:
- API/event version thế nào?
- schema compatibility?
- consumer tracking?
- breaking change policy?
- contract tests?
I - Independent deployability
Câu hỏi:
- build/test/deploy riêng được không?
- deploy không coordinate không?
- rollback được không?
- DB migration an toàn không?
- team có quyền release không?
C - Consistency and data ownership
Câu hỏi:
- database private không?
- transaction boundary là gì?
- saga/outbox/idempotency có không?
- read models/reporting thế nào?
- reconciliation ở đâu?
E - Evidence and observability
Câu hỏi:
- trace xuyên service không?
- event có correlation/causation không?
- service có SLO/dashboards/runbook không?
- deploy marker có không?
- incident điều tra được không?
S - Socio-technical ownership and security
Câu hỏi:
- owner/on-call rõ không?
- cognitive load có chịu nổi không?
- service identity/authorization/secrets ra sao?
- artifact provenance?
- platform/golden path có đủ không?
Tóm tắt:
Microservices trust = boundary đúng + data đúng + contract đúng
+ deploy độc lập + observability + ownership + security.
33. Roadmap áp dụng microservices thực dụng
Giai đoạn 1: monolith có kỷ luật
Mục tiêu:
- domain glossary,
- module boundaries,
- dependency rules,
- internal events,
- outbox cho event quan trọng,
- CI/CD tốt,
- observability baseline.
Không làm:
- tách ồ ạt,
- Kafka/service mesh/Kubernetes nếu chưa cần,
- database per service giả.
Giai đoạn 2: tìm điểm tách có giá trị
Mục tiêu:
- identify bounded contexts,
- pain points: delivery/scale/risk,
- service candidates,
- data ownership plan,
- contract plan,
- migration plan.
Tiêu chí chọn service đầu tiên:
- domain boundary rõ,
- ít transaction chặt với phần còn lại,
- business value rõ,
- team owner rõ,
- rollback/migration manageable.
Giai đoạn 3: extract service đầu tiên đúng cách
Mục tiêu:
- API/event contract,
- private data ownership,
- outbox/CDC,
- read model nếu cần,
- observability,
- on-call/runbook,
- CI/CD/deploy riêng,
- incident path.
Giai đoạn 4: platform hóa
Mục tiêu:
- service catalog,
- golden path,
- default tracing/logging/metrics,
- standard auth/service identity,
- deployment templates,
- contract testing,
- security scanning,
- cost visibility.
Giai đoạn 5: scale service ecosystem
Mục tiêu:
- API/event governance,
- service lifecycle,
- ownership scorecards,
- service mesh nếu cần,
- cell/region strategy,
- deprecation/merge discipline,
- architecture fitness functions.
34. SOTA/practice hiện nay
34.1. Boundary and domain
Thực dụng:
- DDD/bounded context,
- business capability mapping,
- modular monolith first,
- tách service theo điểm tách nghiệp vụ rõ,
- Team Topologies alignment.
Đánh đổi:
- domain discovery tốn thời gian,
- boundary thay đổi,
- team structure cũng phải đổi.
34.2. Data and consistency
Thực dụng:
- database per service,
- transactional outbox,
- saga/process manager,
- idempotent consumers,
- CQRS/read models,
- data contracts,
- reconciliation.
Đánh đổi:
- eventual consistency,
- reporting phức tạp,
- operational overhead,
- hard debugging.
34.3. API/events
Thực dụng:
- OpenAPI/AsyncAPI,
- contract-first for stable APIs,
- schema compatibility,
- consumer-driven contracts,
- API gateway/BFF where useful.
Đánh đổi:
- governance overhead,
- version proliferation,
- contract tests maintenance.
34.4. Runtime/platform
Thực dụng:
- Kubernetes/serverless/managed runtimes where fit,
- service discovery,
- progressive delivery,
- service catalog,
- OpenTelemetry,
- service mesh only when justified.
Đánh đổi:
- platform complexity,
- cost,
- operational skill requirement.
34.5. Security/supply chain
Thực dụng:
- workload identity,
- mTLS/zero-trust direction,
- least privilege,
- artifact signing/provenance,
- SBOM,
- admission policy,
- runtime security.
Đánh đổi:
- guardrail UX,
- policy noise,
- migration complexity.
35. Những bẫy senior phải tránh
Bẫy 1: microservices vì "scale"
Scale nào? Traffic, team, data, risk hay region? Nếu không rõ, microservices là thuốc quá mạnh.
Bẫy 2: tách theo database table
Table không phải bounded context.
Bẫy 3: shared database
Shared database biến service boundary thành lời nói.
Bẫy 4: event như log dump
Event là contract domain, không phải row changed.
Bẫy 5: saga không có state machine
Workflow phân tán mà không có trạng thái rõ sẽ khó debug và recover.
Bẫy 6: E2E test gánh mọi thứ
E2E toàn hệ làm deploy chậm và flaky.
Bẫy 7: service mesh quá sớm
Mesh giải quyết communication platform problem, không giải quyết boundary/domain problem.
Bẫy 8: observability sau cùng
Microservices không trace được thì gần như không vận hành được.
Bẫy 9: independent deployability giả
Deploy riêng nhưng release lockstep vẫn là coupling.
Bẫy 10: không có platform
Mỗi team tự chế CI/CD/logging/security là entropy tăng rất nhanh.
Bẫy 11: không gộp lại khi cần
Nếu hai service luôn đổi/deploy/fail cùng nhau, có thể boundary sai.
Bẫy 12: quên con người
Microservices là architecture cho organization. Team không chịu nổi thì architecture không bền.
36. Kết luận
Microservices là một công cụ mạnh, nhưng không phải cấp bậc tiến hóa bắt buộc của mọi hệ.
Điểm senior nhìn khác junior là:
Junior thấy nhiều service.
Senior thấy independent deployability.
Junior thấy Docker/Kubernetes.
Senior thấy boundary, data ownership và team ownership.
Junior thấy event-driven.
Senior thấy outbox, idempotency, schema contract và replay.
Junior thấy service mesh.
Senior thấy runtime coupling, security, telemetry và platform burden.
Junior thấy scale.
Senior thấy tradeoff giữa delivery independence và distributed complexity.
Một microservices architecture tốt không bắt đầu bằng "tách nhỏ".
Nó bắt đầu bằng:
- domain boundary rõ,
- ownership rõ,
- data ownership rõ,
- contracts rõ,
- platform đủ,
- observability đủ,
- delivery đủ trưởng thành,
- và một lý do kinh doanh/kỹ thuật đủ mạnh để trả chi phí phân tán.
Câu chốt:
Microservices tốt là khi mỗi service là một boundary sống:
có domain rõ, dữ liệu rõ, contract rõ, owner rõ, deploy độc lập,
observe được, recover được, và tạo ít coordination hơn so với trước.
37. Nguồn tham khảo
[^fowler-microservices]: Martin Fowler, "Microservices". https://martinfowler.com/articles/microservices.html [^fowler-distributed]: Martin Fowler, "Microservices and the First Law of Distributed Objects". https://www.martinfowler.com/articles/distributed-objects-microservices.html [^fowler-prerequisites]: Martin Fowler, "Microservice Prerequisites". https://martinfowler.com/bliki/MicroservicePrerequisites.html [^fowler-bounded-context]: Martin Fowler, "Bounded Context". https://martinfowler.com/bliki/BoundedContext.html [^fowler-strangler]: Martin Fowler, "Strangler Fig Application". https://martinfowler.com/bliki/StranglerFigApplication.html [^cncf-microservices]: CNCF Cloud Native Glossary, "Microservices Architecture". https://glossary.cncf.io/microservices-architecture/ [^cncf-service-mesh]: CNCF Cloud Native Glossary, "Service Mesh". https://glossary.cncf.io/service-mesh/ [^microservices-patterns]: Microservices.io, "A pattern language for microservices". https://microservices.io/patterns/index.html [^database-per-service]: Microservices.io, "Database per Service". https://microservices.io/patterns/data/database-per-service.html [^saga]: Microservices.io, "Saga". https://microservices.io/patterns/data/saga.html [^transactional-outbox]: Microservices.io, "Transactional Outbox". https://microservices.io/patterns/data/transactional-outbox.html [^api-gateway-pattern]: Microservices.io, "API Gateway". https://microservices.io/patterns/apigateway.html [^independent-deployability]: Microservices.io, "Essential characteristics: independently deployable". https://microservices.io/post/architecture/2022/05/04/microservice-architecture-essentials-deployability.html [^debezium-outbox]: Debezium, "Outbox Event Router". https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html [^aws-microservices]: AWS, "Implementing Microservices on AWS". https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/microservices-on-aws.html [^tw-microservices]: Thoughtworks, "Microservices". https://www.thoughtworks.com/en-us/insights/decoder/m/microservices [^tw-evolutionary]: Thoughtworks, "Microservices as an Evolutionary Architecture". https://www.thoughtworks.com/insights/blog/microservices-evolutionary-architecture [^sam-bff]: Sam Newman, "Backends For Frontends". https://samnewman.io/patterns/architectural/bff/ [^sam-site]: Sam Newman. https://samnewman.io/ [^openapi]: OpenAPI Specification. https://learn.openapis.org/specification/ [^asyncapi]: AsyncAPI Specification. https://www.asyncapi.com/docs/reference/specification/v3.0.0 [^opentelemetry]: OpenTelemetry Documentation. https://opentelemetry.io/docs/ [^istio]: Istio Documentation. https://istio.io/latest/docs/ [^spiffe]: SPIFFE. https://spiffe.io/ [^dora-2024]: DORA, Accelerate State of DevOps Report 2024. https://dora.dev/report/2024/ [^sre-slo]: Google SRE Book, Service Level Objectives. https://sre.google/sre-book/service-level-objectives/ [^team-topologies]: Team Topologies. https://teamtopologies.com/ [^slsa]: SLSA. https://slsa.dev/ [^nist-ssdf]: NIST SP 800-218, Secure Software Development Framework. https://csrc.nist.gov/pubs/sp/800/218/final