IRPC Specification v1.0
1. Introduction
IRPC (Isomorphic Remote Procedure Call) is a language-agnostic pattern that enables remote function calls with the same ergonomics as local function calls. This specification defines the core concepts, protocols, and interfaces required for interoperable IRPC implementations across different programming languages and environments.
1.1 Scope
This specification defines:
- The IRPC function contract and execution model
- The wire protocol for request/response communication
- The transport abstraction layer including routing
- The factory interface for creating and managing IRPC functions
- The batching and optimization mechanisms
This specification explicitly excludes:
- Specific transport protocol implementations (HTTP, WebSocket, etc.)
- Authentication and authorization mechanisms
- Deployment topologies and infrastructure requirements
- Language-specific implementation details
1.2 Design Goals
IRPC aims to:
- Eliminate cognitive overhead of network communication
- Provide isomorphic function signatures regardless of execution location
- Enable transport-agnostic implementations
- Support type preservation across boundaries
- Optimize performance through intelligent batching
2. Core Concepts
2.1 IRPC Function
An IRPC function is a named, asynchronous function with a fixed signature that can be executed locally or remotely. The function signature remains identical regardless of execution context.
Properties:
- Name: Unique identifier within a namespace
- Parameters: Ordered list of serializable values
- Return Value: Promise that resolves to a serializable value or rejects with an error
- Isomorphism: Same signature and behavior locally and remotely
2.2 Stub and Handler
- Stub: Client-side callable proxy with the same signature as the remote function
- Handler: Server-side implementation containing the business logic
Both stub and handler MUST share identical type signatures.
2.3 Factory
A factory is a callable interface that:
- Creates IRPC function definitions
- Registers handler implementations
- Manages function discovery and routing
- Configures runtime behavior
2.4 Transport
A transport is a pluggable mechanism that:
- Carries serialized IRPC requests and responses
- Handles network-specific details
- Maintains connection management
- Provides protocol-agnostic communication
- Includes routing functionality to map requests to handlers
2.5 Module
A module represents a namespace for IRPC functions with:
- Name and version identification
- Transport configuration
- Timeout settings
- Function registry
3. Data Model
3.1 Primitive Types
IRPC supports the following primitive data types:
- String
- Number (integer and floating-point)
- Boolean
- Null
- Undefined (where applicable in the host language)
3.2 Composite Types
IRPC supports:
- Object: Key-value pairs with string keys and IRPC data values
- Array: Ordered list of IRPC data values
3.3 Serialization
All IRPC data MUST be serializable to a format that can be transmitted across the transport layer. Implementations SHOULD use JSON or equivalent format that preserves the data model.
4. Wire Protocol
4.1 Request Format
{
"id": "string",
"name": "string",
"args": [...]
}Fields:
id: Unique identifier for the request (string)name: Name of the IRPC function to invoke (string)args: Array of arguments to pass to the function
4.2 Response Format
{
"id": "string",
"name": "string",
"result": ...,
"error": "string"
}Fields:
id: Identifier matching the request (string)name: Name of the function that was called (string)result: Return value if successful (optional)error: Error message if failed (optional)
Constraints:
- Exactly one of
resultorerrorMUST be present idMUST match the corresponding request
4.3 Batch Protocol
Transports MUST support batch requests containing multiple IRPC requests in a single transmission.
Batch Request:
[
{"id": "1", "name": "func1", "args": [...]},
{"id": "2", "name": "func2", "args": [...]}
]Batch Response:
While the response format is an array, implementations MUST stream individual responses as they become available, not waiting for all requests to complete:
[
{"id": "1", "name": "func1", "result": ...},
{"id": "2", "name": "func2", "error": "..."}
]Each individual response in the array should resolve immediately when ready, enabling parallel processing and faster response times for individual requests within the batch.
5. Function Specification
5.1 Function Definition
An IRPC function is defined by the following structure (shown in TypeScript syntax as an example):
// Example TypeScript syntax - implementations should use language-appropriate syntax
interface IRPCSpec {
name: string;
schema?: {
input?: ValidationSchema[];
output?: ValidationSchema;
};
description?: string;
}5.2 Validation Schema
Validation schemas are OPTIONAL and MUST NOT affect function signatures. They MAY be used for:
- Input validation before handler execution
- Output validation before response transmission
- Documentation generation
- Development tooling
Validation errors SHOULD be surfaced as transport errors.
6. Transport Interface
6.1 Transport Contract
All transports MUST implement the following interface (shown in TypeScript syntax as an example):
// Example TypeScript syntax - implementations should use language-appropriate syntax
interface IRPCTransport {
send(calls: IRPCCall[]): Promise<IRPCResponse[]>;
}6.2 Routing Functionality
Transports MUST include routing capabilities that:
- Map incoming requests by name to registered handlers
- Validate request format and parameters
- Handle error propagation
- Support request/response correlation
6.3 Call Management
Transports MUST:
- Accept arrays of calls for batching
- Preserve request-response correlation
- Handle network errors appropriately
- Support timeout management
6.4 Streaming Responses
Transports MAY support streaming responses for improved performance, where individual responses are transmitted as they become available.
7. Factory Interface
7.1 Factory Methods
Factories MUST expose the following interface (shown in TypeScript syntax as an example):
// Example TypeScript syntax - implementations should use language-appropriate syntax
interface IRPCFactory {
// Create IRPC function
<F>(spec: IRPCSpec): F;
// Register handler implementation
construct<F>(irpc: F, handler: F): void;
// Configure transport
use(transport: IRPCTransport): void;
// Get function specification
get(name: string): IRPCSpec;
// Configure module settings
configure(config: Partial<IRPCModule>): void;
// Resolve request to handler
resolve<R>(req: IRPCRequest): Promise<R>;
// Get namespace information
get namespace(): IRPCNamespace;
}7.2 Namespace Management
Factories MUST support namespacing to avoid function name collisions (shown in TypeScript syntax as an example):
// Example TypeScript syntax - implementations should use language-appropriate syntax
interface IRPCNamespace {
name: string;
version: string;
description?: string;
}8. Execution Model
8.1 Call Flow
- Client Invocation: Stub function called with arguments
- Request Creation: Request object created with unique ID
- Batching: Request queued for batch transmission
- Transport: Batch sent via configured transport
- Routing: Request routed to appropriate handler by transport
- Handler Execution: Business logic executed
- Response Creation: Response object created
- Transport Return: Response transmitted back
- Promise Resolution: Client promise resolved or rejected
8.2 Error Handling
Errors MUST be propagated through the transport layer as error strings in the response. Implementations SHOULD preserve error context where possible.
8.3 Timeout Management
Factories MUST support configurable timeouts for remote calls. Timeouts SHOULD result in promise rejection.
9. Batching and Optimization
9.1 Automatic Batching
Implementations SHOULD automatically batch multiple IRPC calls made within a short time window to reduce network overhead.
9.2 Connection Reuse
Transports SHOULD reuse connections for multiple requests to improve performance.
9.3 Lazy Loading
Implementations SHOULD support lazy loading of IRPC functions to minimize resource usage.
10. Context Management
10.1 Request Context
Factories MAY support context propagation across request boundaries for:
- Authentication information
- Request tracing
- Custom metadata
10.2 Context Interface
// Example TypeScript syntax - implementations should use language-appropriate syntax
interface IRPCContext<K, V> {
get(key: K): V | undefined;
set(key: K, value: V): void;
has(key: K): boolean;
delete(key: K): boolean;
}11. Security Considerations
11.1 Authentication and Authorization
Authentication and authorization are out-of-band concerns and MUST NOT modify function signatures. Transports MAY enforce authorization via lifecycle hooks.
11.2 Input Validation
Implementations SHOULD validate inputs before handler execution to prevent injection attacks and malformed data.
11.3 Transport Security
Transports SHOULD support secure communication channels (TLS, WSS, etc.) when operating over untrusted networks.
12. Implementation Guidelines
12.1 Language-Agnostic Requirements
All IRPC implementations MUST:
- Implement all required interfaces
- Support the defined wire protocol
- Implement the transport interface with routing
- Provide the factory methods
- Support batching and optimization
12.2 Type Preservation
Implementations SHOULD preserve type information where the host language supports it, enabling:
- Compile-time validation
- IDE support
- Refactoring safety
- Self-documenting APIs
12.3 Error Semantics
Implementations MUST:
- Preserve error messages across boundaries
- Maintain stack traces where possible
- Distinguish between transport and business logic errors
13. Conformance
13.1 Required Conformance
To be IRPC-compliant, an implementation MUST:
- Implement all required interfaces
- Support the wire protocol exactly
- Maintain isomorphic function signatures
- Handle errors according to this specification
- Include routing within the transport layer
13.2 Optional Features
Implementations MAY include:
- Additional validation schemas
- Custom transport protocols
- Advanced optimization strategies
- Enhanced debugging capabilities
14. Versioning and Compatibility
14.1 Specification Versioning
This specification follows semantic versioning. Major version changes indicate breaking changes to the wire protocol or required interfaces.
14.2 Backward Compatibility
Implementations SHOULD maintain backward compatibility within major versions. Changes to the wire protocol require a major version increment.
14.3 Feature Detection
Implementations MAY provide feature detection mechanisms to negotiate capabilities between client and server.
15. Examples
15.1 Function Definition
// Example TypeScript syntax - implementations should use language-appropriate syntax
// Define IRPC function
const readFile = irpc<(path: string, encoding?: string) => Promise<string>>({
name: 'readFile',
schema: {
input: [z.string(), z.string().optional()],
output: z.string(),
},
});15.2 Handler Implementation
// Example TypeScript syntax - implementations should use language-appropriate syntax
// Implement handler
irpc.construct(readFile, async (path, encoding) => {
return await fs.readFile(path, encoding);
});15.3 Client Invocation
// Example TypeScript syntax - implementations should use language-appropriate syntax
// Invoke remotely
const content = await readFile('file.txt', 'utf8');16. Migration Guide
16.1 From REST
- Replace endpoint definitions with IRPC function specifications
- Convert request/response handling to function signatures
- Remove manual serialization logic
- Implement handlers instead of route controllers
16.2 From gRPC
- Replace proto files with IRPC specifications
- Convert service definitions to function registrations
- Maintain existing handler logic with updated signatures
17. Reference Implementation
The TypeScript implementation in this repository serves as the reference implementation for this specification. Language-specific implementations should follow the same patterns and behaviors.
18. Change Log
v1.0
- Initial specification release
- Defined core concepts and wire protocol
- Established transport interface with routing
- Specified factory interface requirements
- Specified batching and optimization requirements
This specification is version 1.0. Future revisions must maintain the invariants defined herein unless superseded by a major version with explicit migration guidance.