Golang / GoLang System Architecture and Testing Interview Questions
What makes a Go microservice horizontally scalable and what patterns break scaling?
A horizontally scalable service can handle more load by adding replicas — each replica is identical and stateless. Go services are well-suited to horizontal scaling due to small memory footprint, but certain patterns break scalability.
| Pattern | Scalable? | Problem / Fix |
|---|---|---|
| Global in-memory cache (map/slice) | NO | Each replica has its own cache — inconsistent reads. Fix: use Redis or Memcached |
| In-memory session store | NO | Sessions are lost on pod restart. Fix: Redis-backed sessions |
| Background goroutine per replica | Caution | N replicas run N workers — duplicated work. Fix: use a job queue with exactly-one semantics |
| Stateless request handler | YES | Each request fully handled without shared state |
| Externally stored state (DB, cache) | YES | State survives restarts; any replica can handle any request |
| Distributed locks (Redis SETNX) | YES | Enables exactly-one execution across replicas for cron jobs |
| Idempotent API | YES | Clients safely retry on any replica |
// ANTI-PATTERN: in-memory state that breaks horizontal scaling var sessionStore = map[string]Session{} // lost on pod restart! // CORRECT: external session storage type SessionStore struct{ redis *redis.Client } func (s *SessionStore) Get(ctx context.Context, id string) (*Session, error) { data, err := s.redis.Get(ctx, "sess:"+id).Bytes() if err != nil { return nil, err } var sess Session return &sess, json.Unmarshal(data, &sess) } // Distributed cron: only one replica should run a job func runIfLeader(ctx context.Context, rdb *redis.Client, jobFn func()) { key := "job:lock:daily-report" acquired, err := rdb.SetNX(ctx, key, "1", 5*time.Minute).Result() if err != nil || !acquired { return // another replica has the lock } defer rdb.Del(ctx, key) // release after job jobFn() }
More Related questions...