Skip to content

Target Go Microservices Architecture ​

Phase: Architecture target with staged implementation Status: active; bounded native foundations, task packs, and non-default route rehearsals exist, while default routes remain proof-gated. Rule: this document is binding for Go foundation and cutover work; legacy source remains read-only.

Objective ​

Build a new Go backend under go-platform/ using Parallel Rewrite plus Strangler Fig. The current NestJS backend stays live while the Go API Gateway migrates one route group at a time from legacy proxy mode to native Go service mode.

The first target is compatibility, not redesign. Public /api/... routes, token shape, Vietnamese feature labels, import review behavior, SSE events, and exam/attempt snapshot semantics must remain stable until an explicit frontend migration phase.

Runtime Topology ​

ComponentRoleExternal SurfaceInternal Surface
api-gatewayPublic compatibility gateway and auth context propagation/api/*, /api/health/*, /metricsHTTP to Go services, HTTP proxy to legacy API
bff-serviceOptional web/admin aggregation layer for screen-shaped responsesFrontend may call only api-gateway or gateway-approved BFF routes; no direct owner-service hostnamesHTTP to owner services
iam-serviceAccount identity, credentials, JWT/JWKS, sessions, roles, permissions, access-control membershipsGateway onlyHTTP/gRPC-style JSON, events
profile-serviceEducational user profiles, student/teacher/parent/staff metadata, public profile viewsGateway onlyHTTP, events
organization-service (school-service current)Organizations, schools/centers/campuses, units, tenant metadata, tenant validation, and IAM-synchronized membership read modelsGateway onlyHTTP, events
classroom-serviceClassrooms, members, teacher assignments, class activity/read modelsGateway onlyHTTP, events
course-serviceCourses, sections, lessons, enrollments, progressGateway onlyHTTP, events
file-service (document-service current)Files/media assets, S3/MinIO object metadata, teaching documentsGateway onlyHTTP, object storage
import-service (docx-import-service current)DOCX/PDF/OCR import jobs, parsed previews, review drafts, approval orchestrationGateway only, SSE through gatewayHTTP, worker, events
formula-docx-service (go-formula-docx runtime behind docx-import-service)DOCX/formula/table parsing and parser metricsInternal onlyHTTP/runtime worker
ai-service (ai-classifier-service current)AI classify/generate/explain/grade foundations, provider settings, usage eventsGateway only, SSE through gatewayHTTP, worker, events
question-service (question-bank-service current)Questions, answers, solutions, versions, folders, groups, tags, question types/taxonomy refsGateway onlyHTTP, events
exam-serviceExam authoring, folders, blueprints, templates, publish snapshots, assignmentsGateway onlyHTTP, events
attempt-serviceAttempt creation, answer save, submit, grading, attempt events/resultsGateway onlyHTTP, events
notification-serviceNotifications, preferences, event fanoutGateway onlyHTTP, events
analytics-serviceRead models for progress/results/mastery/dashboardGateway onlyHTTP, event consumers
billing-servicePlans, prices, subscriptions, invoices, commercial entitlementsGateway onlyHTTP, events
wallet-serviceAZ Credits, wallet balances, immutable credit ledger, grants/debits/refundsGateway onlyHTTP, events
usage-service (entitlement-service alias)Quota periods, usage counters, feature gates, entitlement checksGateway onlyHTTP, events
payment-servicePayment orders, provider transactions, webhooks, reconciliationGateway onlyHTTP, events
search-serviceSearch indexes and sync checkpoints for copied/indexed dataGateway onlyHTTP, event consumers
audit-serviceAppend-only compliance/security event history, retention metadata, and producer replay targetsGateway onlyHTTP, event consumers
admin-serviceFeature maintenance, admin dashboard/read models, operational controlsGateway onlyHTTP, events

Wallet/AZ Credit public routes, subscription, billing, search, and standalone audit remain legacy-proxied until the corresponding Go service task pack is implemented and gateway route cutover evidence exists. payment-service has a native foundation for payment orders and webhook idempotency, and wallet-service has a native foundation for immutable AZ Credit ledger idempotency. billing-service has a native foundation for plan catalog, subscription, invoice, and entitlement idempotency. usage-service has a native foundation for entitlement materialization, quota counters, limit overrides, and idempotent check/consume/reset decisions, but the gateway must still keep /api/wallet, package/subscription, AI/import quota callers, and payment/webhook routes proxied unless a later task explicitly promotes a route group. search-service has a native foundation for rebuildable content indexes and sync checkpoints, but public search/catalog routes stay legacy-proxied until owner-service indexing and gateway route parity are documented. audit-service has a native append-only compliance/security event foundation, but public admin audit remains controlled by the existing admin-service/gateway route rehearsal until compatibility and backfill evidence are explicit. bff-service has a native no-primary-DB screen aggregation foundation for admin/teacher dashboard and operations shells plus frontend route metadata, but browser clients still reach it only through API Gateway route promotion. The current Go implementation also intentionally splits attempt-service from the broader exam domain and analytics-service from admin/operational dashboards so attempt runtime state and analytical projections have their own databases, task packs, and verification flows.

Platform Choices ​

ConcernChoiceRationale
LanguageGoTarget rewrite language.
HTTP routerchiLightweight, explicit middleware chain, easy gateway adapters.
DB driverpgxNative Postgres support and good pooling.
SQL generationsqlcCompile-time checked SQL while keeping query ownership explicit.
Migrationsservice-local SQL plus tools/migrator schema runnerCurrent Compose/K8s/Helm bootstrap runs schema-up --service=<service> against each service-owned database and records applied files in schema_migrations.
Cache/queueRedis initiallyLegacy already depends on Redis/BullMQ; easier strangler compatibility.
Event busNATS or Redis StreamsNATS preferred for new domains; Redis Streams acceptable for early local parity.
Object storageS3-compatible MinIOPreserve existing storage deployment and object keys.
Loggingslog or zapStructured JSON logs with request/correlation IDs.
MetricsPrometheusPreserve /metrics operational model.
TracingOpenTelemetryRequired for gateway-to-service and worker traces.
API docsOpenAPILegacy contract snapshot plus Go service contracts.
Local runtimeDocker Compose first, kind laterCompose is enough for initial service skeleton and route parity.

Request Flow ​

  1. Frontend continues calling /api/....
  2. api-gateway assigns or forwards X-Request-Id and X-Correlation-Id.
  3. Gateway validates access token compatibility where needed, then creates an internal auth context.
  4. Gateway chooses route target:
    • migrated route -> Go service
    • unmigrated route -> legacy Nest API
  5. Gateway normalizes response envelope and error shape when the native service does not yet match legacy shape.
  6. Gateway streams SSE for import/classification/attempt event routes without buffering full responses.

Service Communication Rules ​

  • Services never read each other's databases.
  • Synchronous calls are allowed only for user-facing request completion.
  • Cross-domain side effects use events and idempotent consumers.
  • No distributed transactions in Phase 2.
  • IAM owns permission-bearing organization membership writes. The current school-service/organization-service membership rows are synchronized read models for tenant validation and compatibility.
  • For exam attempts, snapshot data crosses boundaries by value, not by live foreign-key dependency.
  • Gateway can call multiple services only when preserving a legacy route requires aggregation.

Data Ownership ​

Each service owns its own Postgres database. During migration, services may have read-only adapters against the legacy database for backfill and parity verification, but runtime writes must go to exactly one owning service database unless the route is still legacy-proxied.

Observability Baseline ​

Every binary must expose:

  • /healthz
  • /readyz
  • /metrics
  • structured JSON logs with request_id, correlation_id, service, route, status, duration_ms
  • OpenTelemetry trace propagation using W3C trace context

The gateway additionally keeps legacy-compatible:

  • /api/health/live
  • /api/health/ready
  • /api/metrics if legacy clients depend on it

Security Baseline ​

  • JWT secrets and provider credentials are environment-only.
  • No production default secrets.
  • Gateway enforces public route allowlist.
  • Service-to-service calls include internal identity.
  • Tenant context is explicit: organization_id is part of request context, not an implicit global.
  • Admin routes require both authenticated role and explicit admin policy check.

First Native Domains ​

Recommended first native implementation order:

  1. api-gateway proxy-only mode with health, metrics, tracing.
  2. iam-service, profile-service, and organization-service identity/profile/tenant foundations.
  3. file-service storage metadata read path and presigned upload compatibility.
  4. import-service job shell and event model, initially wrapping existing Go Formula DOCX behavior.
  5. question-service question types and read-only question list parity.
  6. exam-service exam read parity, then draft authoring.
  7. attempt-service answer save/submit only after snapshot contract is proven.
  8. billing-service, wallet-service, usage-service, and payment-service before any AZ Credits/subscription route cutover.
  9. notification-service, search-service, audit-service, admin-service, and analytics-service for operations, discovery, compliance, and dashboard read models once owner-service events/backfills are explicit.

Reasoning: DOCX import and question-bank are high-value, but storage/media and gateway observability are prerequisites for reliable import migration.

Go-platform documentation is generated from repository Markdown.