Chapter 8 Flashcards — Reuse Patterns

flashcards saht reuse-patterns sidecar service-mesh shared-library


What are the four code reuse patterns in distributed architectures?
?

  1. Code Replication — copy the code into each service
  2. Shared Library — versioned build-time artifact (JAR, npm package, etc.)
  3. Shared Service — runtime service called via network
  4. Sidecar / Service Mesh — infrastructure sidecar process alongside each service

What is code replication and when is it appropriate?
?
Code replication means copying shared code into each service that needs it — no shared artifact, no dependency. It is appropriate only when: the code is small and trivial, it is used by 2-3 services, it is unlikely to change, and divergence between copies is acceptable. It fails at scale when the shared logic requires consistent updates across all consumers.


What is the biggest risk of code replication?
?
Silent divergence: copies of the shared code drift apart over time without detection. A bug fix applied to one service’s copy is forgotten in other copies. At scale (10+ services), manually tracking and updating all copies becomes impossible, and behavioral inconsistencies surface as production bugs.


What is a shared library and what is its dominant challenge?
?
A shared library is a versioned, compiled artifact (JAR, npm package, NuGet, etc.) that services import as a build-time dependency. Its dominant challenge is change management: when the library changes, how do consumers learn about it, when must they upgrade, and how are breaking changes handled? Without versioning discipline and change control, a shared library creates worse coupling than it solves.


What are the three versioning strategies for shared libraries?
?

  1. Pinned version: each service pins to a specific version (lib:2.3.1) and upgrades on its own schedule. Risk: consumers lag far behind current version.
  2. Semantic versioning with deprecation: SemVer (MAJOR.MINOR.PATCH) plus a policy that old major versions are supported for N months. Forces eventual upgrades.
  3. Single version (no pinning): all consumers must always use the current version. Only works when one team owns all consumers.

What does semantic versioning (SemVer) communicate about library changes?
?
MAJOR.MINOR.PATCH version numbers communicate the nature of changes:

  • MAJOR increment: breaking change — existing consumers must update their code to remain compatible
  • MINOR increment: backward-compatible new feature added — consumers can upgrade without code changes
  • PATCH increment: backward-compatible bug fix — safe to upgrade without code changes

When should you choose a shared library over other reuse patterns?
?
Use a shared library when: (1) the shared code is stable and changes infrequently, (2) all consumers use the same programming language/runtime, (3) the shared logic is performance-critical (cannot afford a network call), and (4) you have the governance discipline to maintain versioning and change control. Also appropriate for infrastructure/utility code (logging helpers, retry utilities, common DTOs).


What is the primary limitation of shared libraries in polyglot environments?
?
A shared library is language-specific — a Java library cannot be used by a Python service. In polyglot distributed systems, each language needs its own implementation of the shared library, which means maintaining multiple implementations in sync — effectively multiplying the change management problem. This makes shared services or sidecars more attractive in polyglot environments.


What is a shared service and how does it differ from a shared library?
?
A shared service extracts shared logic into a standalone runtime service called via the network (HTTP, gRPC, or messaging). Unlike a shared library (build-time dependency, in-process), a shared service is a runtime dependency — changes take effect immediately for all consumers upon deployment. It is language-agnostic (any consumer that can make a network call can use it) but introduces network latency and a shared point of failure.


What are the two key weaknesses of the shared service pattern?
?

  1. Performance: every call crosses a network boundary, adding 10-100ms of latency per call. For frequently-called shared logic (e.g., authorization checks on every request), the cumulative latency impact can be significant.
  2. Fault tolerance: the shared service is a single point of failure (SPOF). If it fails, all consumers are simultaneously impacted. A bug in the shared service cascades to every dependent service at once.

When does the shared service pattern make sense despite its trade-offs?
?
Use a shared service when: (1) the logic is runtime-variable (changes based on live configuration or database state — cannot be baked into a library), (2) the system is polyglot and a language-neutral API is required, (3) the logic needs independent scaling or security controls, or (4) centralized behavioral consistency is a strong requirement (all consumers must get updated logic immediately upon deployment).


What mitigation strategies are essential when using a shared service?
?

  1. Circuit breakers on all consumers — prevent cascading failures when the shared service is slow or down
  2. Multiple instances — no single-instance deployment; run redundant replicas across zones
  3. Asynchronous consumption where possible — put requests on a queue so the shared service processes them asynchronously, decoupling its availability from the consumer’s critical path
  4. Backward-compatible API changes — consumers must not be broken by shared service deployments
  5. Comprehensive monitoring and SLAs — the shared service now has many dependents; treat it as critical infrastructure

What is a sidecar in the context of distributed architecture?
?
A sidecar is a separate process or container deployed alongside each service (in the same Kubernetes pod or same host). It handles cross-cutting infrastructure concerns — logging, metrics collection, distributed tracing, service discovery, health checking, circuit breaking, mTLS encryption, and rate limiting — so the service code can focus purely on domain logic. The service and sidecar communicate via localhost (fast local IPC).


What specific problem does the sidecar pattern solve that shared libraries cannot?
?
Shared libraries solve reuse within the same language. Sidecars solve infrastructure reuse across all languages: since the sidecar is a separate process communicating via localhost (not language-level APIs), a Python service and a Java service and a Go service all get the same infrastructure capabilities from the same sidecar — no language-specific library implementation needed. Additionally, infrastructure can be upgraded by updating the sidecar — without redeploying or changing any service code.


What is a service mesh and how does it relate to sidecars?
?
A service mesh is a dedicated infrastructure layer that coordinates all sidecars across the system. It has two planes:

  • Data plane: the sidecars themselves (e.g., Envoy proxies) that intercept and handle traffic alongside each service
  • Control plane: the mesh management layer (e.g., Istio, Linkerd) that configures all sidecars centrally — enforcing policies, routing rules, mTLS certificates, and observability settings across the entire system

The service mesh makes “configure infrastructure for all services” a single operation rather than N separate operations.


What capabilities does a service mesh provide beyond what individual sidecars can do?
?
The service mesh control plane adds: (1) Centralized policy enforcement — apply a circuit-breaking or retry policy to all services without touching any service code, (2) Uniform observability — traffic flowing through all sidecars gives complete topology mapping, latency metrics, and error rates, (3) mTLS everywhere — mutual TLS between all services enforced at the mesh layer without per-service certificate management, (4) Traffic management — canary deployments, A/B testing, and traffic shifting controlled centrally, (5) Fine-grained authorization — “service A may only call service B on endpoint X” enforced at the network layer.


How does sidecar performance compare to a shared service?
?
Sidecar is much faster than a shared service. A sidecar communicates with its co-located service via localhost (loopback) — a local IPC call that is nearly as fast as an in-process call. A shared service call crosses a real network boundary, adding 10-100ms per call. Sidecars bring near-in-process performance to the shared functionality they handle, making them appropriate for high-frequency concerns like request tracing and circuit breaking.


What types of logic are appropriate for each reuse pattern?
?

PatternAppropriate Logic
Code ReplicationTrivial utilities; divergence acceptable
Shared LibraryStable domain or infrastructure logic; same language
Shared ServiceRuntime-variable domain logic; polyglot; consistency-critical
Sidecar/MeshInfrastructure concerns only — logging, tracing, circuit breakers, mTLS, health checks

The most important distinction: sidecars handle infrastructure concerns, not domain/business logic.


When is a service mesh NOT the right choice?
?
A service mesh is NOT appropriate when: (1) the system has few services (< 10) — the operational overhead of the mesh is not amortized across enough services to justify it, (2) the environment is homogeneous (one language) and a shared library suffices, (3) the team lacks platform engineering expertise to operate Istio/Linkerd/Consul Connect, or (4) the organization is early-stage and adding mesh complexity would slow development significantly.


In the Sysops Squad saga, why was the sidecar pattern chosen for infrastructure concerns?
?
The Sysops Squad services were polyglot — a shared library would require multiple language implementations. The infrastructure team wanted to update tracing and security without triggering service redeployments. A shared library would require service teams to upgrade and redeploy. The sidecar pattern solves both: one sidecar implementation works across all languages, and updating the sidecar doesn’t require touching service code.


In the Sysops Squad saga, why was a shared service chosen for notification logic instead of a shared library?
?
(1) The notification rules change based on business decisions — a library update would require redeploying all consumers (ticket service, survey service, billing service) in coordination. (2) Behavioral consistency is critical — customers must receive consistent notifications regardless of which service triggers them. (3) The consuming services were polyglot. A shared service allows the notification rules to be updated by deploying only the notification service, with all consumers immediately using the new rules.


What is “reuse via platforms” and why is it considered the architectural ideal?
?
Rather than teams sharing code via libraries or services, reuse via platforms means investing in shared infrastructure that all teams consume: a logging platform, a tracing platform, a service mesh, a secrets manager, an identity provider. Teams get reuse through infrastructure consumption, not code ownership. This eliminates: (1) language coupling (platforms are API-driven), (2) per-team implementation inconsistency, and (3) the need for each team to become experts in cross-cutting infrastructure concerns.


What is the key difference in how change risk manifests for shared library vs. shared service?
?

  • Shared library: change risk manifests at build time — a breaking change in the library causes compilation failures or test failures in consumer services. Consumers are protected by pinned versions and can upgrade on their own schedule.
  • Shared service: change risk manifests at runtime — a bug deployed to the shared service immediately impacts all consumers in production. There is no version pinning to protect consumers. This requires rigorous canary deployments, backward-compatible API evolution, and strong testing before deployment.

Complete this principle: “Infrastructure concerns should use ___, while domain logic should use ___.”
?
“Infrastructure concerns should use sidecars (service mesh), while domain logic should use shared libraries (if stable and same-language) or shared services (if runtime-variable, polyglot, or requiring centralized consistency).” The key is that sidecars are not appropriate for business/domain logic — they are specifically for cross-cutting operational concerns.


What governance mechanism is most important for managing shared libraries at scale?
?
A change control process for breaking changes: (1) breaking changes require advance notice to all consumers (e.g., 4-6 weeks), (2) a new major version is released with a migration guide, (3) the old major version is officially deprecated with a support end date, (4) consumers must upgrade before the deprecation deadline. Without this process, shared libraries either stagnate (no one upgrades) or cause surprise breakage (breaking changes without notice).


Why might code replication actually be the correct choice in some microservice architectures?
?
In cases where services are owned by completely independent teams or organizations, where each team legitimately needs different behavior from nominally “shared” logic, and where the cost of coordination (versioning, change control, API design) exceeds the cost of maintaining separate copies — code replication is correct. It maximizes independence at the cost of consistency, which is an acceptable trade-off when consistency is not a hard requirement.



Total Cards: 26
Priority: HIGH
Last Updated: 2026-05-30