Golang / GoLang System Architecture and Testing Interview Questions
How do you decide where to draw service boundaries when decomposing a Go monolith into microservices?
Service decomposition is one of the hardest architectural decisions. Decomposing too aggressively creates a 'distributed monolith' — all the complexity of microservices with none of the benefits. Decomposing too conservatively keeps the monolith's disadvantages.
| Principle | Description | Go Implication |
|---|---|---|
| Domain-Driven Design | Split by bounded context — User, Order, Inventory are separate domains | Each service owns its schema; no cross-schema JOINs |
| Single Responsibility | Each service does one thing well; change one thing without touching others | One binary per domain; small team ownership |
| Data Ownership | Service owns its data; others access via API — no shared DB tables | Separate databases or schemas; eventual consistency via events |
| Deployability | Can each service be deployed independently? | Separate CI/CD pipelines; semantic versioning of gRPC APIs |
| Failure Isolation | Does one service's failure propagate? | Circuit breakers; timeout on every cross-service call |
| Strangler Fig | Migrate gradually — route traffic by feature flag | Proxy in Go; run old+new in parallel |
// Anti-pattern: too-fine decomposition (nanoservices) // UserNameService, UserEmailService, UserAgeService // â Every user operation requires 3 network calls // â Synchronous coupling worse than a monolith // Better: domain-aligned decomposition // UserService: manage user profiles and authentication // OrderService: manage order lifecycle and payments // NotifyService: send emails/SMS/push â consumes events from others // Strangler Fig pattern in Go func routeToNewService(cfg *Config) http.Handler { legacyHandler := newLegacyHandler() newHandler := newModernHandler() return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Gradually shift traffic using feature flags if cfg.Features.IsEnabled("new-user-service") && strings.HasPrefix(r.URL.Path, "/users/") { newHandler.ServeHTTP(w, r) return } legacyHandler.ServeHTTP(w, r) }) }
More Related questions...