Mesh Protocol Specification
Mesh Protocol Specification
Section titled “Mesh Protocol Specification”An intra-service RPC protocol with per-function versioning
Protocol Version: 0.1.0 (Draft)
Overview
Section titled “Overview”Mesh is a JSON-based RPC protocol designed for internal microservice communication. It prioritizes:
- Per-function versioning — Evolve functions independently, not monolithic API versions
- Built-in observability — Tracing context propagates through call chains
- Explicit retry semantics — Idempotency and deadlines are first-class
- Extensibility — Clean extension mechanism for optional features
- Simplicity — Easy to implement in any language
Quick Start Guide
Section titled “Quick Start Guide”Get a Mesh endpoint running in 5 minutes:
1. Define Your Function
Section titled “1. Define Your Function”{ "function": "users.get", "version": "1", "description": "Retrieve a user by ID", "arguments": { "type": "object", "properties": { "id": { "type": "integer" } }, "required": ["id"] }}2. Build a Request
Section titled “2. Build a Request”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_001", "call": { "function": "users.get", "version": "1", "arguments": { "id": 42 } }}3. Return a Response
Section titled “3. Return a Response”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_001", "result": { "id": 42, "name": "Jane Doe", "email": "jane@example.com" }}4. Handle Errors
Section titled “4. Handle Errors”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_001", "result": null, "errors": [{ "code": "NOT_FOUND", "message": "User not found", "retryable": false }]}5. Add Observability (Optional)
Section titled “5. Add Observability (Optional)”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_001", "call": { "function": "users.get", "version": "1", "arguments": { "id": 42 } }, "context": { "trace_id": "tr_abc123", "caller": "api-gateway" }}See Protocol for complete field definitions.
Specification Documents
Section titled “Specification Documents”Core Protocol
Section titled “Core Protocol”| Document | Description |
|---|---|
| Protocol | Request and response structure, field definitions |
| Document Structure | Top-level structure of requests and responses |
| Errors | Error handling, error codes, multiple errors, source pointers |
| Versioning | Protocol versioning and per-function versioning |
Data & Resources
Section titled “Data & Resources”| Document | Description |
|---|---|
| Resource Objects | Standard structure for domain entities (type/id/attributes) |
| Relationships | Including and querying related resources |
| Sparse Fieldsets | Request only the fields you need |
| Filtering | Query filter syntax and operators |
| Sorting | Sort criteria for collection queries |
| Pagination | Standard patterns for paginated list operations |
Request Features
Section titled “Request Features”| Document | Description |
|---|---|
| Context | Context propagation for tracing and metadata |
| Rate Limiting | Rate limit communication and handling |
Extensions
Section titled “Extensions”| Document | Description |
|---|---|
| Extensions | Extension mechanism for optional capabilities |
| Async | Asynchronous operation patterns |
| Deadline | Request timeouts to prevent cascading failures |
Transport
Section titled “Transport”| Document | Description |
|---|---|
| Transport | HTTP and message queue bindings |
System
Section titled “System”| Document | Description |
|---|---|
| System Functions | Reserved namespaces and built-in functions |
| Description | Machine-readable API description (OpenRPC-style) |
Terminology
Section titled “Terminology”The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in these documents are to be interpreted as described in RFC 2119.
Complete Example
Section titled “Complete Example”Request
Section titled “Request”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_xyz789", "call": { "function": "orders.create", "version": "2", "arguments": { "customer_id": 42, "items": [ { "sku": "WIDGET-01", "quantity": 2 } ] } }, "context": { "trace_id": "tr_8f3a2b1c", "span_id": "sp_4d5e6f", "caller": "checkout-service" }, "extensions": [ { "urn": "urn:mesh:ext:deadline", "options": { "value": 5, "unit": "second" } } ]}Success Response
Section titled “Success Response”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_xyz789", "result": { "order_id": 12345, "status": "pending" }, "extensions": [ { "urn": "urn:mesh:ext:tracing", "data": { "trace_id": "tr_8f3a2b1c", "span_id": "span_server_001", "duration": { "value": 127, "unit": "millisecond" } } } ], "meta": { "node": "orders-api-2" }}Error Response
Section titled “Error Response”{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_xyz789", "result": null, "errors": [ { "code": "INVALID_ARGUMENTS", "message": "Customer not found", "retryable": false, "source": { "pointer": "/call/arguments/customer_id" } } ], "extensions": [ { "urn": "urn:mesh:ext:tracing", "data": { "trace_id": "tr_8f3a2b1c", "span_id": "span_server_002", "duration": { "value": 23, "unit": "millisecond" } } } ], "meta": { "node": "orders-api-1" }}Transport
Section titled “Transport”Mesh is transport-agnostic. Common transports:
- HTTP — POST to service endpoint, JSON body
- Message Queue — Async processing via RabbitMQ, Redis, etc.
- Unix Socket — Local inter-process communication
See Transport for detailed bindings.
Implementation Checklist
Section titled “Implementation Checklist”Use this checklist when implementing a Mesh client or server:
Server Implementation
Section titled “Server Implementation”- Parse and validate
protocolfield (reject unknown versions) - Echo
idfield in all responses - Route requests by
call.functionandcall.version - Validate
call.argumentsagainst function schema - Return
errorobject for single errors,errorsarray for multiple - Include
code,message, andretryablein all errors - Support
source.pointerfor validation errors (JSON Pointer format) - Implement standard error codes (
NOT_FOUND,INVALID_ARGUMENTS, etc.) - Handle deadline extension — return
DEADLINE_EXCEEDEDif exceeded - Propagate
context.trace_idandcontext.span_idto downstream calls - Include
meta.durationin responses
Client Implementation
Section titled “Client Implementation”- Generate unique
idfor each request - Use deadline extension for all production calls
- Propagate trace context from incoming requests
- Handle both
erroranderrorsresponse formats - Implement retry logic based on
error.retryable - Use exponential backoff for retryable errors
- Respect
Retry-Afterhints in rate limit errors
Optional Features
Section titled “Optional Features”- Extensions: Declare in
extensionsarray withurnandoptionsobjects - Async: Implement
mesh.operation.statuspolling - Idempotency: Use idempotency extension for safe retries
- Discovery: Implement
mesh.functionsfor introspection - Health: Implement
mesh.healthwith component checks
JSON-RPC Migration Guide
Section titled “JSON-RPC Migration Guide”Migrating from JSON-RPC 2.0 to Mesh:
| JSON-RPC | Mesh | Notes |
|---|---|---|
jsonrpc: "2.0" | protocol: "mesh/0.1" | Version identifier |
method | call.function | Function name |
| — | call.version | New: Per-function versioning |
params (array/object) | call.arguments | Always object |
result | result | Same semantics |
error.code (integer) | errors[].code (string) | String codes: NOT_FOUND, INVALID_ARGUMENTS |
error.message | errors[].message | Same semantics |
error.data | errors[].details | Renamed |
| — | errors[].retryable | New: Explicit retry hint |
| — | errors[].source | New: JSON Pointer to error location |
| — | context | New: Trace propagation |
| — | extensions | New: Optional capabilities (deadline, tracing, etc.) |
| — | meta | New: Response metadata |
Key Differences
Section titled “Key Differences”-
No notifications — All requests require responses. Use async extension for fire-and-forget with tracking.
-
No batch requests — Make concurrent HTTP/2 requests instead. See FAQ for rationale.
-
Per-function versioning — Version each function independently instead of the entire API.
-
String error codes — Use descriptive
SCREAMING_SNAKE_CASEcodes instead of integers. -
Built-in observability — Trace context propagates automatically through
contextfield.
Migration Example
Section titled “Migration Example”JSON-RPC 2.0:
{ "jsonrpc": "2.0", "id": 1, "method": "users.get", "params": { "id": 42 }}Mesh:
{ "protocol": { "name": "mesh", "version": "0.1.0" }, "id": "req_001", "call": { "function": "users.get", "version": "1", "arguments": { "id": 42 } }}Pagination Decision Matrix
Section titled “Pagination Decision Matrix”Choose the right pagination strategy for your use case:
| Strategy | Best For | Trade-offs |
|---|---|---|
| Offset | Admin UIs, simple lists, “jump to page” | Inconsistent on writes, slow for large offsets |
| Cursor | Infinite scroll, real-time feeds | No random access, opaque tokens |
| Keyset | Large datasets, time-series | Requires stable sort column, no count |
Decision Flowchart
Section titled “Decision Flowchart”Need "jump to page N"? └─ Yes → Offset pagination └─ No → Dataset > 10K rows? └─ Yes → Keyset pagination └─ No → Real-time feed? └─ Yes → Cursor pagination └─ No → Cursor or Offset (preference)Quick Examples
Section titled “Quick Examples”Offset — Page 3 of 10 items:
{ "page": { "offset": 20, "limit": 10 } }Cursor — After specific position:
{ "page": { "after": "eyJpZCI6MTAwfQ==", "limit": 10 } }Keyset — After specific value:
{ "page": { "after": { "created_at": "2024-01-15T10:30:00Z", "id": 500 }, "limit": 10 } }See Pagination for complete specification.
Security Considerations
Section titled “Security Considerations”Authentication
Section titled “Authentication”Mesh does not specify authentication — it is a transport concern. Common patterns:
- HTTP: Bearer tokens in
Authorizationheader - Message Queues: Credentials in connection/channel configuration
- mTLS: Certificate-based service identity
Authorization
Section titled “Authorization”Use the context field to propagate identity for authorization decisions:
{ "context": { "caller": "checkout-service", "user_id": "usr_123", "roles": ["admin", "billing"] }}Servers SHOULD validate authorization before processing and return FORBIDDEN for unauthorized requests.
Input Validation
Section titled “Input Validation”- Always validate
call.argumentsagainst your schema - Use
source.pointerto indicate exact location of invalid input - Sanitize all user input before use in queries or commands
- Limit request body size at transport layer (recommended: 1 MB)
Rate Limiting
Section titled “Rate Limiting”- Implement rate limits per caller/function
- Return
RATE_LIMITEDwithretry_afterin details - Use
context.callerto identify requesting service - See Rate Limiting for response format
Secrets
Section titled “Secrets”- Never include secrets in
call.argumentsfor logging safety - Use reference IDs instead of raw credentials
- Redact sensitive fields in error details
Changelog
Section titled “Changelog”0.1.0 (Draft)
Section titled “0.1.0 (Draft)”- Initial specification
- Core protocol, errors, versioning
- Document structure and resource objects (JSON:API-style)
- Filtering with operators (equals, in, between, like, etc.)
- Sorting and sparse fieldsets
- Relationship inclusion and nested queries
- Context propagation
- Rate limiting with proactive visibility (IETF draft headers)
- Pagination patterns (offset, cursor, keyset)
- Extension mechanism
- Async patterns
- Transport bindings (HTTP, message queues)
- System functions and reserved namespaces
- Health protocol (mesh.health) with component-level checks
- Discovery specification (OpenRPC-style introspection)