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.