NYSSR.NET / RESOURCES
Use one message model across the network
See how nyssr.net uses one asynchronous message model for local calls, distributed workflows, events, replies, and cross-node routing.
When a system needs local calls, cross-site workflows, events, and replies without separate communication models, one consistent message boundary can reduce integration work.
In nyssr.net, services do not primarily communicate through shared state or a chain of HTTP endpoints. They communicate by sending messages to objects that may live on the same node, another node, or somewhere else in the mesh.
A message is more than a data packet. It is a typed unit of work with a destination, transport instructions, and a lifecycle that can include processing, forwarding, and a reply.
One message, two responsibilities
Every message separates what is being said from how it should travel:
- The record carries the business data: fields, values, structures, and arrays.
- The envelope carries transport information: sender, receiver, result status, priority, compression, encryption, and reply behavior.
The envelope handles transport; the record carries the data.
This separation lets the same message format work for a local request, a cross-node notification, or a response that travels back through the mesh.
Key idea: A record describes the work; an envelope makes the work deliverable, observable, and controllable.
Typed data without rigid service coupling
Records can be assembled dynamically, but most production messages are described in JSON or XML. From that description, applications can generate typed classes for creating and reading messages.
A record definition might look like this:
{
"name": "NODE_ADDED",
"description": "A remote node joined the network.",
"slots": [
{ "name": "REMOTE_NODE", "type": "NODE_ADDRESS" },
{ "name": "TYPE", "type": "STRING" }
]
}
The important boundary is the message contract, not the implementation class behind the service. A service can add fields over time while older consumers continue to use the fields they understand.
Asynchronous by default
Sending a message does not block the sender until the receiver has finished. The sender registers or invokes a handler, then continues its own work. When the message arrives, the system calls the handler in the target's processing context.
That model is useful when a service needs to:
- start work that involves several other services
- notify observers without waiting for them
- process many independent requests
- keep the application responsive while a result is being prepared
A handler can return a result, send a notification, forward the message, or hold it while another internal request is completed.
Replies form a built-in handshake
Messages can request a response. After processing, the receiver can return the message with a result code and optional result text. The sender therefore knows whether the request succeeded, failed, or could not reach its target.
This handshake is part of the message lifecycle rather than an extra API convention. It supports ordinary requests as well as notifications, broadcasts, and multi-step workflows.
Messages connect objects directly, independent of the node on which they run.
Routed through the node mesh
The sender does not need to open a new connection to the receiver for every message. Nodes maintain channels to their neighbors and forward messages along the best available route.
Routes have a cost based on connection conditions such as forwarding time. Each node observes the network and can choose another path when a connection fails or a better route becomes available.
- Local messages stay local
- Remote messages cross existing node channels
- Failed connections can be bypassed
- The receiver can be in a cloud, branch office, or private network
The mesh chooses a suitable route instead of relying on one central broker.
More than request and response
The same message model supports several communication patterns:
- Requests ask a target to perform work and return a result
- Notifications announce an event without requiring a response
- Broadcasts reach multiple interested targets
- Forwarded messages continue through another service or node
- Deferred messages remain active while a workflow completes
Messages can also carry priority information. Answers and control messages can be handled ahead of lower-priority traffic. Compression and encryption can be requested per message or configured for a node.
Key idea: One communication primitive supports local calls, distributed workflows, events, and resilient cross-node routing.
What this changes for application design
With messages as the boundary between services, applications do not need to know where every service is running or how it is implemented. They need a message contract and a target identity.
That makes it possible to move a service closer to its data, run several instances for load balancing, or replace its implementation without rewriting every caller.
Contract: Define the data exchanged between services, independently of their internal classes.
Concurrency: Let handlers and targets perform work asynchronously instead of blocking threads.
Resilience: Use result codes, replies, forwarding, and alternate routes to make failure visible and recoverable.
For the API details, continue with the Messages documentation. For the wider architecture, return to the nyssr.net overview.