ADR-0005: Define Synchronous Service Communication
- Status: Accepted
- Date: 2026-10-08
- Decision Owners: Zelvoryqa Architecture
- Technical Area: Service Communication / Distributed Systems
- Related ADRs:
- ADR-0001: Adopt Microservices Based on Business Capabilities
- ADR-0002: Adopt Multi-Tenant SaaS Architecture
- ADR-0003: Define Service Data Ownership and Tenant Data Isolation
- ADR-0004: Adopt Event-Driven Integration
Context
Zelvoryqa is designed as a multi-tenant SaaS platform composed of independently deployable services aligned to business capabilities.
ADR-0001 establishes that services own their business capabilities and communicate through explicit integration boundaries.
ADR-0002 establishes that one organization corresponds to one logical tenant boundary and that organization context must be preserved and enforced across distributed operations.
ADR-0003 establishes that services own their operational data and that direct cross-service database access is prohibited.
ADR-0004 establishes event-driven integration as a primary mechanism for asynchronous communication between services.
Although asynchronous integration supports loose coupling, independent consumers, and eventual consistency, some business operations require immediate interaction with another service.
Examples include:
- Retrieving authoritative inventory availability
- Validating customer information
- Requesting inventory reservations
- Retrieving current order information
- Checking shipment status
- Validating organization-scoped business constraints
- Requesting an operation owned by another service
These interactions require a defined synchronous communication model.
Without explicit synchronous communication rules, Zelvoryqa risks:
- Tight runtime coupling between services
- Cascading failures
- Excessive synchronous dependency chains
- Unbounded request latency
- Unsafe retries and duplicate business operations
- Unauthorized cross-service access
- Cross-tenant data exposure
- Bypassing authoritative business logic
- Inconsistent error handling
- Ambiguous transaction boundaries
- Difficult operational troubleshooting
Zelvoryqa therefore requires a consistent approach to synchronous service communication that preserves service autonomy, authoritative ownership, tenant isolation, resilience, and operational visibility.
Decision
Zelvoryqa will use explicit synchronous service APIs for operations requiring an immediate response, authoritative information, or an immediate business outcome.
Synchronous communication will complement event-driven integration rather than replace it.
Calling services must interact with another service's business capability through its published API contract.
A synchronous call does not transfer authority over the receiving service's business logic or operational data.
The architecture will establish requirements for:
- Appropriate use of synchronous communication
- Explicit service contracts
- Authoritative service ownership
- Service-to-service authentication
- Organization context propagation
- Authorization and tenant isolation
- Request deadlines and timeouts
- Retry safety and idempotency
- Error handling
- Failure isolation
- Distributed consistency
- Observability and traceability
- Contract evolution
The specific transport protocols, frameworks, identity mechanisms, and implementation libraries will be selected separately.
Synchronous Communication Uses Explicit Service Contracts
Services must communicate synchronously through explicitly defined APIs.
Conceptually:
Order Service
|
| Request inventory availability
v
Inventory Service API
|
v
Inventory Service Business Logic
|
v
Inventory Operational Data
|
v
Inventory Service Response
|
v
Order Service
The calling service sends a request and waits for a response or a defined failure outcome.
The receiving service controls:
- Its published API contract
- Request validation
- Authorization
- Organization ownership validation
- Business rules
- Operational data access
- Business state changes
- Response semantics
Calling services must not bypass the receiving service's published contracts by accessing its internal databases or implementation details.
Authoritative Service Ownership Must Be Preserved
A synchronous request does not transfer authority over the receiving service's business capability.
For example, the Order Service may request an inventory reservation from the Inventory Service.
Order Service
|
| Request inventory reservation
v
Inventory Service
|
| Validate request
| Enforce organization boundary
| Apply inventory business rules
| Reserve inventory
v
Inventory Operational Data
The Inventory Service remains authoritative for inventory availability and reservations.
The Order Service remains authoritative for orders.
The Inventory Service may return a reservation identifier, status, or other contract-defined result.
The Order Service may use that result to update its own order state.
The Order Service must not directly modify inventory records or independently assume authority over inventory reservation rules.
The same ownership principle applies to all service-to-service interactions.
Synchronous Communication Must Be Used Selectively
Synchronous communication is appropriate when a caller requires an immediate response to continue an operation.
Examples include:
- Retrieving current authoritative information
- Requesting a business operation that must return an immediate outcome
- Validating information owned by another service
- Performing an operation where the caller must know whether the receiving service accepted or completed the request
Asynchronous event-driven communication is generally preferred when:
- A service is announcing a completed business fact
- Multiple independent consumers may react
- The producer does not require an immediate downstream result
- Downstream processing can occur eventually
- Analytical projections or notifications can be updated asynchronously
- A workflow benefits from reduced runtime coupling
Conceptually:
Immediate response required
|
v
Synchronous Service API
Business fact to distribute
|
v
Event-Driven Integration
These patterns are complementary.
A business workflow may use both synchronous APIs and asynchronous events.
Synchronous calls must not be introduced solely to notify unrelated services of business state changes when an event would provide a more appropriate integration boundary.
Service-to-Service Authentication Is Required
Internal service communication must not be considered trusted solely because it occurs within private infrastructure or a shared network.
The receiving service must be able to establish the identity of the calling service or workload using an approved authentication mechanism.
Conceptually:
Order Service
|
| Authenticated service request
v
Inventory Service
|
| Verify calling workload identity
v
Authorize requested operation
Service identity establishes which workload is making the request.
It does not automatically establish permission to access every organization or business resource.
The exact authentication mechanism will be defined by the security architecture and related implementation decisions.
Organization Context Must Be Preserved
Synchronous service communication involving organization-owned resources must preserve sufficient organization context to enforce the appropriate tenant boundary.
Conceptually:
Authenticated User
|
v
Order Service
|
| Organization A Context
| Request inventory reservation
v
Inventory Service
|
| Authenticate caller
| Validate organization context
| Authorize operation
| Enforce resource ownership
v
Organization A Inventory
An organization identifier carried in a request identifies the organization but does not automatically establish trusted or authorized organization context.
The receiving service must evaluate the caller's identity, the organization context, the requested operation, and relevant resource ownership.
A request originating from another authenticated service must not automatically receive unrestricted tenant access.
Missing, invalid, or untrusted organization context must not result in platform-level access.
Organization-scoped operations must fail when the required organization context cannot be established.
Platform-level operations must use explicitly defined and separately authorized capabilities.
Authorization Must Be Enforced by the Receiving Service
The receiving service remains responsible for enforcing access to its own business capability and organization-owned resources.
Authorization must not depend solely on:
- The API Gateway
- The calling service
- The caller's network location
- Authentication alone
- Client-provided organization identifiers
- Upstream authorization decisions
- User interface restrictions
Upstream authentication and authorization may contribute to defense in depth.
However, the receiving service must enforce the authorization requirements applicable to its published operation and resource ownership boundary.
For example:
Order Service
|
| Organization A
| Inventory reservation request
v
Inventory Service
|
+---- Validate service identity
+---- Validate organization context
+---- Authorize reservation operation
+---- Verify resource ownership
|
v
Organization A Inventory
The Inventory Service must reject requests that attempt to access or modify another organization's inventory without an explicitly authorized capability.
The detailed authorization model will be defined in ADR-0006.
Request Deadlines and Timeouts Are Required
Synchronous requests must have bounded execution times.
A calling service must not wait indefinitely for another service to respond.
Timeout and deadline policies must consider:
- Expected operation latency
- Network latency
- Remaining request deadline
- Dependency behavior
- Downstream processing requirements
- Resource consumption
- User-facing response expectations
Conceptually:
Client Request
|
v
Order Service
|
| Remaining request deadline
v
Inventory Service
|
v
Response or Timeout
Each synchronous request must have a bounded deadline or timeout appropriate to the operation being performed.
When a request is part of a larger synchronous operation, downstream calls must respect the remaining overall deadline. Services may establish shorter operation-specific timeouts, but must not extend an existing upstream deadline.
Cancellation should propagate through synchronous dependencies where supported so that unnecessary processing can stop when the initiating request is canceled or its deadline expires.
Cancellation does not guarantee that a state-changing operation was rolled back or did not complete. Operations that may have committed before cancellation must be handled through appropriate idempotency, status verification, or reconciliation mechanisms.
Durable asynchronous workflows may continue independently of the original request when explicitly designed to do so.
Timeouts must not be interpreted as proof that a requested business operation did not execute.
A receiving service may have completed an operation even if the response was lost or the caller timed out.
Retries Must Be Bounded and Safe
Synchronous calls may encounter transient failures involving networks, infrastructure, or downstream services.
Retries must use controlled policies that account for:
- Retryable versus non-retryable failures
- Request deadlines
- Maximum retry attempts
- Backoff
- Jitter where appropriate
- Downstream capacity
- Business operation semantics
- Duplicate side effects
- Tenant isolation
Retries must not continue indefinitely.
Retries must not be applied indiscriminately to every operation or error.
A request that modifies business state must not be retried unless duplicate execution can be handled safely.
Retry policies should avoid multiplying retries across multiple layers of a distributed call chain.
Idempotency Must Protect Retried Business Operations
Synchronous operations that may be retried must provide appropriate protection against duplicate business effects.
For example:
Order Service
|
| Reserve 5 units
v
Inventory Service
|
| Reservation succeeds
|
X Response lost
|
v
Order Service retries request
The Inventory Service must not create a second reservation simply because the original response was lost.
Possible safeguards include:
- Idempotency keys
- Business operation identifiers
- Uniqueness constraints
- Conditional state transitions
- Transactional safeguards
- Returning a previously recorded operation result
The specific approach depends on the operation and implementation.
Idempotency must be enforced within the authoritative service's business boundary. An operation must be idempotent in its actual implementation, not merely in how its API or RPC contract is defined. Repeating the same request for the same logical business operation must not produce unintended additional business effects, such as creating duplicate inventory reservations, deducting inventory multiple times, or generating duplicate orders.
For example, if the Order Service requests an inventory reservation and the Inventory Service successfully processes it but the response is lost, a retry must not create another reservation for the same business operation.
The authoritative service may enforce idempotency through appropriate mechanisms, such as idempotency keys, unique business operation identifiers, database constraints, or conditional state transitions. These safeguards must remain effective across concurrent requests and service restarts.
Error Handling Must Be Explicit
Synchronous service contracts must define meaningful error semantics.
Errors should distinguish between:
- Invalid requests
- Authentication failures
- Authorization failures
- Missing resources
- Business rule violations
- Conflicts
- Rate limits or resource exhaustion
- Dependency failures
- Temporary unavailability
- Deadlines and timeouts
- Internal service failures
Calling services must not assume that all errors are retryable.
Error responses must provide enough information for appropriate handling without exposing sensitive implementation details or unauthorized organization data.
A timeout or interrupted connection may leave the outcome of a state-changing operation unknown. The receiving service may have successfully committed the operation even though the calling service did not receive a response. Calling services must not assume that a timeout or communication failure means the requested operation was not executed.
Error handling must distinguish between a confirmed business failure and an unknown operation outcome.
When an operation's outcome is unknown, the calling service must use an appropriate recovery mechanism, such as checking the operation's status, safely retrying with the same idempotency key, or reconciling the resulting business state.
The exact HTTP status codes, RPC error mappings, and error envelope formats will be defined through API contract decisions.
Failure Isolation Must Be Preserved
Synchronous dependencies introduce runtime coupling.
A failure or slowdown in one service must not unnecessarily exhaust resources in its callers or propagate across unrelated services.
Possible safeguards include:
- Request timeouts
- Concurrency limits
- Connection limits
- Bounded retries
- Backpressure
- Circuit breakers where appropriate
- Bulkheads or workload isolation
- Graceful degradation
- Dependency health monitoring
For example:
Order Service
|
| Inventory unavailable
v
Bounded Timeout
|
v
Defined Failure Response
The Order Service must not wait indefinitely or consume unbounded resources while Inventory Service is unavailable.
Graceful degradation is appropriate only when it does not violate required business invariants.
For example, a system must not confirm an inventory reservation merely because the Inventory Service is unavailable.
Synchronous Dependency Chains Must Be Limited
Long synchronous call chains increase latency and failure propagation risk.
For example:
API Gateway
|
v
Order Service
|
v
Inventory Service
|
v
Warehouse Service
|
v
Shipping Service
Each dependency introduces additional latency and potential failure.
Service designs should minimize unnecessary synchronous call depth.
A service should not introduce a downstream synchronous dependency when an asynchronous event, local derived representation, or different workflow boundary would satisfy the business requirement.
When multiple synchronous calls are necessary, the implementation must account for their combined latency and failure characteristics.
Distributed Transactions Must Not Be Assumed
A synchronous API call does not create a shared atomic transaction across services.
For example:
Order Service
|
| Create order
v
Order Operational Data
Order Service
|
| Reserve inventory
v
Inventory Service
|
v
Inventory Operational Data
The Order Service and Inventory Service maintain independent persistence and transaction boundaries.
Successfully committing an order does not guarantee that an inventory reservation will also succeed.
Likewise, successfully reserving inventory does not guarantee that a later order update will succeed.
Workflows spanning multiple services must explicitly address:
- Partial success
- Unknown outcomes
- Recovery
- Compensation where appropriate
- Reconciliation
- Idempotency
- Business state transitions
Possible approaches include stateful workflow coordination, compensating operations, or asynchronous follow-up processing.
This ADR does not mandate a particular distributed transaction or workflow coordination pattern.
Consistency Requirements Must Be Explicit
Synchronous communication may provide an immediate response from an authoritative service, but it does not automatically guarantee global consistency across multiple services.
A service may return its current authoritative state while another service's derived representation remains temporarily stale.
For example:
Inventory Service
|
| Authoritative inventory state
v
Synchronous API Response
Inventory Service
|
| InventoryReserved event
v
Event Bus
|
v
Operations Intelligence
|
v
Eventually Updated Projection
Consumers must distinguish between authoritative operational state maintained by the service that owns the business capability and derived data maintained by other services. Derived data may be updated asynchronously through events and can temporarily differ from the current authoritative state.
Operations requiring current authoritative information should use an appropriate contract with the owning service or an explicitly defined consistency mechanism.
A synchronous read must not be assumed to reserve or lock the data it returns.
For example, checking inventory availability and subsequently requesting a reservation are separate operations unless the Inventory Service defines a contract that combines them atomically within its own boundary.
Service Contracts Must Support Independent Evolution
Synchronous service contracts must support controlled evolution without requiring all calling and receiving services to deploy simultaneously.
Contract changes must consider:
- Backward compatibility
- Required and optional fields
- Error semantics
- API versioning
- Deprecation
- Consumer migration
- Contract testing
- Authentication and authorization requirements
Services must not rely on undocumented internal endpoints or implementation details.
The detailed API versioning and compatibility strategy will be defined separately.
Observability and Traceability
Synchronous service communication must provide sufficient observability to investigate requests across service boundaries.
Operational visibility should support questions such as:
- Which service initiated the request?
- Which service received it?
- Which operation was requested?
- Did the operation succeed?
- How long did the request take?
- Did it time out?
- Was it retried?
- Which dependency failed?
- Which organization was affected?
- Was authorization denied?
- Did the request produce a business state change?
Observability may include:
- Structured logs
- Distributed traces
- Request and correlation identifiers
- Request latency metrics
- Error rate metrics
- Timeout metrics
- Retry metrics
- Dependency health metrics
- Resource saturation metrics
Tracing context should be propagated across synchronous service boundaries.
Organization context should be available where appropriate for tenant-aware investigation without exposing unauthorized organization data.
Organization identifiers must be used cautiously as metric labels because unbounded organization-level dimensions may create excessive metric cardinality.
The detailed observability implementation will be defined separately.
Rationale
Preserve Authoritative Service Ownership
Explicit service APIs allow callers to request information or operations without directly accessing another service's operational database or bypassing its business rules.
Support Immediate Business Requirements
Some operations require immediate authoritative information or a defined response before processing can continue.
Synchronous communication provides a direct interaction model for those requirements.
Complement Event-Driven Integration
Using synchronous APIs selectively avoids forcing every business interaction into asynchronous workflows.
Event-driven integration remains the primary mechanism for distributing completed business facts to independent consumers.
Enforce Tenant Isolation
Authenticated service calls preserve organization boundaries only when the receiving service validates the relevant identity, context, authorization, and resource ownership.
Control Failure Propagation
Bounded deadlines, safe retries, concurrency controls, and explicit failure handling reduce the risk of cascading failures across synchronous dependencies.
Support Independent Evolution
Explicit, versioned service contracts reduce coupling to internal implementations and support independent service development and deployment.
Maintain Clear Consistency Boundaries
Treating service transactions as independent prevents incorrect assumptions about cross-service atomicity and encourages explicit recovery and reconciliation mechanisms.
Alternatives Considered
Alternative 1: Event-Driven Communication Only
Services communicate exclusively through asynchronous business events.
Advantages
- Loose runtime coupling
- Independent consumers
- Reduced direct availability dependencies
- Natural support for eventual consistency
Disadvantages
- Difficult immediate request-response interactions
- Additional complexity for authoritative queries
- More complex correlation of requests and results
- Unnecessary workflow complexity for simple synchronous operations
Reason Not Selected
Some Zelvoryqa business operations require immediate responses or authoritative results.
Event-driven integration alone does not efficiently satisfy every interaction pattern.
Alternative 2: Synchronous Communication for All Service Interactions
Services use direct API or RPC calls for all cross-service coordination.
Advantages
- Straightforward request-response behavior
- Familiar interaction model
- Immediate operation results when available
- Easier reasoning about some workflows
Disadvantages
- Strong runtime coupling
- Greater cascading failure risk
- Longer dependency chains
- Downstream availability affects upstream processing
- Poor fit for independent event consumers and analytics
Reason Not Selected
This conflicts with the event-driven integration model established by ADR-0004 and introduces unnecessary coupling.
Alternative 3: Direct Cross-Service Database Access
Services retrieve or modify another service's operational data directly.
Advantages
- Simple cross-domain queries
- Fewer API calls
- Potentially lower latency for some reads
Disadvantages
- Violates authoritative service ownership
- Bypasses business rules
- Couples services to internal schemas
- Weakens independent deployment
- Increases tenant-isolation risk
Reason Not Selected
This violates the service data ownership boundaries established by ADR-0003.
Alternative 4: Selective Synchronous APIs with Event-Driven Integration
Services use explicit synchronous APIs for immediate interactions and business events for asynchronous coordination.
Advantages
- Preserves service ownership
- Supports immediate authoritative responses
- Avoids unnecessary synchronous dependencies
- Complements event-driven workflows
- Enables independent service evolution
- Supports tenant-aware authorization
- Allows consistency requirements to be selected per operation
Disadvantages
- Requires managing two communication patterns
- Synchronous dependencies still introduce runtime coupling
- Requires explicit timeout and retry policies
- Cross-service workflows require careful consistency handling
- Adds contract governance and observability requirements
Reason Selected
This approach provides the best balance between immediate business requirements, service autonomy, resilience, and asynchronous extensibility.
Consequences
Positive Consequences
- Services interact through explicit published contracts.
- Authoritative service ownership is preserved.
- Immediate business interactions are supported.
- Synchronous communication complements event-driven integration.
- Organization context and authorization requirements remain enforceable.
- Timeouts and retry behavior become explicit architectural requirements.
- Cross-service consistency boundaries are recognized.
- Service contracts can evolve independently.
Negative Consequences
- Direct service calls create runtime dependencies.
- Availability and latency of downstream services can affect callers.
- Service authentication and authorization require additional infrastructure and implementation.
- Retry safety and idempotency add complexity.
- Distributed workflows may require compensation or reconciliation.
- API compatibility must be managed across independently deployed services.
- Debugging may involve multiple services and dependencies.
Risks
- Excessive synchronous dependencies may cause cascading failures.
- Missing deadlines may exhaust resources.
- Unsafe retries may duplicate business operations.
- Lost responses may create ambiguous operation outcomes.
- Calling services may incorrectly assume authority over downstream data.
- Inconsistent authorization may expose tenant-owned resources.
- Organization context may be lost across service boundaries.
- Synchronous reads may become stale before subsequent writes.
- Partial cross-service failures may leave workflows incomplete.
- Undocumented APIs may create hidden coupling.
- Long call chains may increase latency and reduce availability.
Implementation Considerations
Future implementation must define:
- Synchronous transport protocols
- Service API conventions
- Request and response contracts
- Service discovery
- Service-to-service authentication mechanisms
- Workload identity and trust boundaries
- Organization context representation and propagation
- Authorization and resource ownership validation
- Request deadlines and timeout policies
- Retry and backoff policies
- Idempotency mechanisms
- Error response conventions
- Connection and concurrency limits
- Circuit breaker and bulkhead requirements
- Cancellation propagation
- Distributed workflow coordination
- Compensation and reconciliation
- API versioning
- Contract testing
- Observability instrumentation
Implementations must preserve the architectural requirements established by this ADR regardless of the selected transport or framework.
Operational Considerations
Synchronous dependencies must be monitored for availability, latency, error rates, timeouts, and resource saturation.
Operational tooling should support investigation of requests across service boundaries.
Dependency failures must be distinguishable from failures originating within the calling service.
Timeouts and retries must be observable so operators can identify degraded dependencies and retry amplification.
Operational procedures must account for unknown outcomes of state-changing requests.
Service-to-service authentication failures and authorization denials must be observable without exposing sensitive information.
Organization context must remain available for tenant-aware investigation where appropriate.
Platform operators may require privileged capabilities for incident response and troubleshooting.
Such access must be explicitly authorized and auditable rather than implemented as an implicit tenant bypass.
Capacity planning must account for:
- Request throughput
- Request latency
- Connection usage
- Concurrent requests
- Downstream service capacity
- Retry amplification
- Dependency saturation
- Organization workload differences
- Noisy-neighbor behavior
- Tenant fairness
Operational monitoring should distinguish service availability from successful completion of business workflows.
A service responding to health checks does not necessarily mean that all of its downstream dependencies are healthy or that every business operation can complete successfully.
Validation
This decision will be considered successfully implemented when Zelvoryqa can demonstrate that:
- Services use explicit API contracts for synchronous communication.
- Services do not directly access another service's operational database.
- Calling services do not bypass the receiving service's business rules.
- Authoritative service ownership remains intact.
- Synchronous calls are used when immediate responses are required.
- Asynchronous events are used where immediate downstream responses are unnecessary.
- Calling services authenticate to receiving services.
- Receiving services enforce authorization for requested operations.
- Organization context is preserved across synchronous boundaries.
- Missing or invalid organization context does not grant unrestricted access.
- Organization A cannot access Organization B's resources through service-to-service calls.
- Requests have bounded deadlines or timeouts.
- Cancellation is propagated where supported.
- Retries are bounded and applied only when safe.
- Retried state-changing operations do not produce unintended duplicate effects.
- Timeouts and lost responses are handled as potentially unknown outcomes.
- Errors are classified and handled according to documented contracts.
- Downstream failures do not cause unbounded resource consumption.
- Synchronous dependency chains are controlled.
- Cross-service operations do not assume shared atomic transactions.
- Partial failures can be detected and handled through defined recovery mechanisms.
- Authoritative reads and derived projections are distinguished appropriately.
- Distributed traces and relevant correlation context cross service boundaries.
- Dependency latency, errors, timeouts, and retries are observable.
- API contract changes can be validated for compatibility.
Follow-Up
The following architectural decisions build on this ADR:
- ADR-0006: Define Authentication, Organization Membership, and Authorization
- ADR-0007: Define API Gateway and External API Architecture
Additional later decisions will define:
- Service-to-service transport and implementation conventions
- Workload identity and secrets management
- API and event contract versioning
- Service reliability and resilience patterns
- Observability architecture
- Distributed workflow coordination patterns
- Rate limiting, quotas, and tenant fairness
- Contract and integration testing
References
- ADR-0001: Adopt Microservices Based on Business Capabilities
- ADR-0002: Adopt Multi-Tenant SaaS Architecture
- ADR-0003: Define Service Data Ownership and Tenant Data Isolation
- ADR-0004: Adopt Event-Driven Integration
- Zelvoryqa Architecture Overview
- Zelvoryqa Product Vision
- Zelvoryqa Goals
Status Definitions
- Proposed — The decision is under review.
- Accepted — The decision has been approved and should guide implementation.
- Deprecated — The decision is no longer recommended but remains for historical context.
- Superseded — The decision has been replaced by a newer ADR.
ADR Guidelines
This ADR records one significant architectural decision.
The ADR should:
- Explain the context that required the decision.
- State the decision clearly.
- Document the reasoning behind the decision.
- Record meaningful alternatives and tradeoffs.
- Separate durable architectural requirements from implementation details.
- Avoid selecting technologies that belong in later decisions.
- Be superseded rather than rewritten when the architectural decision fundamentally changes.