Rusty Mesh is a fast in-memory orchestration layer for microservice/distributed systems. It provides a focused HTTP control plane for service registration, heartbeat-based liveness, semantic version matching, health checks, and sorted round-robin load balancing across compatible instances.
Built with Rust, Axum, and Tokio, Rusty Mesh is designed for teams that want full control over their microservices orchestration layer without needing an external or third-party control plane.
While the project's main focus is the mesh/orchestrator layer, for easier onboarding, the repository also includes a demo-microservices directory with four demo microservices (
order-service - nodejs,user-service - rust,cart-service - python, andcatalog-service - rust) that use the mesh and show how engineering teams can integrate it into their microservice builds.
- Static Analysis/Code Standardization
- Core Capabilities
- Architecture
- Requirements
- Quick Start
- External Endpoint Resolution
- Docker
- Integrating Into A Microservice Project
- API Reference
- Service Discovery Semantics
- Configuration
- Traffic Simulation
- Development
- Testing
- Operational Notes
- License
Rusty Mesh is a Rust service at it's core, but the root build uses JavaScript ecosystem tooling for repository workflow and code-standardization checks. The Node/Bun layer is intentionally limited to developer tooling; the mesh runtime remains Rust-based.
package.jsondefines the Bun-powered workflow scripts.- Husky installs Git hooks through the
preparescript. - Commitlint enforces Conventional Commit messages in
.husky/commit-msg. - Pre-commit checks run
cargo check,cargo fmt -- --check, Clippy with warnings denied, and Markdown formatting. - Pre-push checks run the Rust test suite and Markdown formatting checks.
- Prettier is used for Markdown formatting and documentation consistency.
Install the tooling with:
bun install-
Register service instances by name, semantic version, IP address, and port.
-
Refresh service leases through the dedicated heartbeat endpoint or by re-registering.
-
Unregister service instances explicitly.
-
Discover a compatible service instance using semantic-version requirements.
-
Select compatible service instances with sorted round-robin load balancing.
-
Automatically remove expired service instances using a configured heartbeat interval and TTL.
-
List currently active service instances.
-
Run as a standalone Docker container without the repository
compose.yaml. -
Load configuration from TOML files and
APP__environment variable overrides. -
Protect registry routes with a shared mesh token for internal service-to-service access.
-
Emit structured JSON logs through
tracing. -
More...
Rusty Mesh follows a standard Rust service build structure that is intended to be both clean and maintainable. Below is a breakdown for more context:
src/
main.rs # binary entry point
lib.rs # app state and router assembly
core/
router.rs # versioned route definitions
controllers/registry/ # HTTP handlers
services/registry/ # registry domain logic
structs/ # request/response domain structs
middlewares/ # logging, mesh-auth, and timeout middleware
utils/ # environment and config loading
Routes are mounted under:
/api/v1/mesh
The registry itself is an in-memory HashMap wrapped in async-safe shared state. Each service
instance stores:
nameversionipporttimestamp- optional external endpoint metadata:
external_ip,external_port, andexternal_scheme
Expired entries are removed during register, heartbeat, unregister, find, and list operations. Load-balanced discovery sorts matching instances by name, version, registered internal IP address, and registered internal port, then returns the next instance using a round-robin cursor for that service and version requirement.
Rusty Mesh treats service registration as a heartbeat-driven contract. Registered services should
refresh their lease before registry.service_ttl_secs elapses. Startup validation enforces that
registry.heartbeat_interval_secs is lower than registry.service_ttl_secs, so the configured
policy always leaves room for missed or delayed heartbeats before an instance is considered stale.
- Rust
1.85+ - Cargo
- Docker, optional, for containerized runs
cargo-watch, optional, forcargo dev
- Clone the repository:
git clone https://github.com/okpainmo/rusty-mesh.git- Copy over the
.env.samplefile to.envand update the values as needed:
cp .env.sample .envThe
.envfile exists solely to select the working/deployment environment withAPP__DEPLOY__ENV. Depending on that value, runtime environment values are loaded from one of the environment-specific files. Three environments are supported:development,staging, andproduction.In the main
.env, simply uncomment the preferred environment then leave the rest commented.
- Copy in the environment-specific
.envfiles to the root of the project, and equally update as necessary:
cp .env.development.sample .env.development
cp .env.staging.sample .env.staging
cp .env.production.sample .env.production- Run the mesh server locally:
cargo dev
cargo devusescargo-watchto run the server in watch/development mode. Ifcargo-watchis not installed, runcargo install cargo-watchor usecargo run.
By default, development mode starts the server at:
http://127.0.0.1:3080
Check health:
curl http://127.0.0.1:3080/api/v1/mesh/healthExpected response:
{
"response_message": "Mesh service is healthy",
"response": {
"status": "ok",
"service": "mesh_service",
"registry_policy": {
"heartbeat_interval_secs": 5,
"service_ttl_secs": 15
}
},
"error": null
}Registry routes are protected by a shared mesh token. Send it as a Bearer token on register, discover, list, and unregister requests.
For the mesh server itself, set the token through the active environment file:
APP__SECURITY__MESH_TOKEN=<mesh-token>For demo services, set the matching client-facing token in demo-microservices/.env:
MESH_TOKEN=<mesh-token>The health endpoint remains public so container platforms and load balancers can check liveness without holding the mesh token.
By default, Rusty Mesh only needs the internal endpoint a service registers with. It can also store an externally reachable endpoint for operator-facing discovery responses. This matters when multiple instances of the same service share one stable internal port while the deployment platform assigns dynamic host ports for each replica, or when host-side access to each service instance is required. Continue reading to learn more in the docker resolver section.
External endpoint resolution is explicit and controlled by:
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=<mode>Available modes:
| Mode | Behavior | Production posture |
|---|---|---|
none |
Do not inspect Docker or any platform API. Use explicit external endpoint fields when provided. | Default and safest baseline |
docker |
Inspect the registering Docker container to resolve the host port mapped to its internal port. | Opt-in; requires a trusted control-plane deployment |
The default is none.
Resolution priority is:
-
Use explicit external endpoint fields from the registration request.
-
If no explicit endpoint fields are supplied and the resolver mode is
docker, inspect Docker. -
On discovery response, if no external endpoint can be resolved, fall back to the internal registered endpoint.
In none mode, Rusty Mesh does not inspect Docker or any platform API. This is the production-safe
baseline when the deployment platform, gateway, sidecar, or service config already knows the
externally reachable host and port.
The service sends those values during registration:
{
"service_name": "cart-service",
"service_version": "1.0.0",
"service_port": 30302,
"external_host": "cart.example.com",
"external_port": 443,
"external_scheme": "https"
}external_host and external_port must be provided together. external_scheme is optional and
defaults to http; when provided, it must be http or https.
If a service does not provide an explicit external endpoint, public discovery falls back to the registered internal endpoint.
The Docker resolver exists for dynamic-port deployments where each scaled instance shares the same internal container port, but Docker assigns a different host port. This is common in local Compose stacks and simple Docker-based demos:
ports:
- "30302"In that setup, the service knows it is listening on 30302 inside the container, but it does not
automatically know which random host port Docker assigned. Docker Engine is the source of truth for
that mapping. Rusty Mesh can ask Docker only when this mode is explicitly enabled:
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=dockerThe Docker resolver flow is:
- A service registers with its internal service port, for example
30302. - The service client sends its Docker container id in the
x-mesh-container-idheader. - Rusty Mesh inspects that container through the Docker Engine socket.
- It reads
NetworkSettings.Ports["30302/tcp"][0].HostPortfrom the Docker inspect response. - It stores that host port as the service's external port.
- Public list and discovery responses return
ip,port, andurlusing the external endpoint, plusinternal_ipandinternal_portfor the in-network endpoint.
For example, if Docker maps cart-service-1:30302 to host port 63858, the public registry
response becomes:
{
"name": "cart-service",
"version": "1.0.0",
"ip": "127.0.0.1",
"port": 63858,
"internal_ip": "cart-service-1",
"internal_port": 30302,
"timestamp": 1790745600,
"url": "http://127.0.0.1:63858"
}Internal service-to-service discovery can still request the Docker-network endpoint by sending:
x-mesh-endpoint-scope: internalThat keeps peer calls inside the Docker network while letting operators curl the externally published service URL from the host.
Mounting /var/run/docker.sock into a container is powerful. Even when mounted read-only at the
filesystem level, the Docker Engine API can expose sensitive container, network, image, and runtime
metadata. Treat Docker socket access as privileged infrastructure access, not as a harmless
read-only helper.
Rusty Mesh uses the socket only when APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=docker. In that
mode it inspects the registering container and resolves the host port mapped to the registered
internal port.
Using the Docker resolver in production can be valid when Rusty Mesh is deployed as a trusted control-plane component with strong network isolation, strict mesh-token handling, patched hosts, centralized monitoring, and restricted operator access. In that model, Docker inspection is an intentional control-plane privilege that lets Rusty Mesh resolve runtime endpoint metadata for the services it manages.
Keep these guardrails in place when enabling it:
-
Enable
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=dockeronly for deployments that explicitly trust Rusty Mesh with Docker inspection. -
Do not log or return raw Docker inspect payloads.
-
Keep registry routes private and protected by a strong
APP__SECURITY__MESH_TOKEN. -
Treat
x-mesh-container-idas privileged input from trusted service clients. -
Restrict the Docker host, firewall rules, service network, and operator access so the mesh server cannot be reached from untrusted networks.
You might prefer one of these alternatives when Rusty Mesh should not hold Docker-level privilege:
-
Keep
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=noneand have services register their externally reachable host and port directly when the deployment platform provides them. -
Put Rusty Mesh behind the same orchestrator or service-discovery layer as the services and use internal endpoints only.
-
Use a restricted sidecar or proxy that exposes only the small inspect data Rusty Mesh needs.
-
In Kubernetes(if Rusty Mesh ever applies), use pod/service metadata from the Kubernetes API instead of Docker socket access.
Rusty Mesh includes a standalone Docker setup. The mesh service image can be plugged into any
distributed system of choice, then wired into that system's central Compose or orchestration setup.
Build the image:
docker build -t rusty-mesh .Run the container:
docker run --rm \
-p 3080:3080 \
-e APP__SECURITY__MESH_TOKEN=<add-mesh-token> \
rusty-meshThe Docker image defaults to:
APP__ENV=production
APP__SERVER__HOST=0.0.0.0
APP__SERVER__PORT=3080
APP__REGISTRY__HEARTBEAT_INTERVAL_SECS=5
APP__REGISTRY__SERVICE_TTL_SECS=15
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=none
APP__SECURITY__REQUIRE_MESH_TOKEN=true
Override runtime configuration when needed:
docker run --rm \
-p 4080:4080 \
-e APP__SERVER__PORT=4080 \
-e APP__REGISTRY__HEARTBEAT_INTERVAL_SECS=10 \
-e APP__REGISTRY__SERVICE_TTL_SECS=30 \
-e APP__SECURITY__MESH_TOKEN=replace-with-a-strong-token \
rusty-meshIf you want Rusty Mesh inside an existing microservice workspace, simply add it as a standalone service in your parent repository's microservices directory.
Move into the parent services directory:
cd <microservice-services-dir>Clone the mesh service with the folder name you want to use in the parent project:
git clone --single-branch --branch main https://github.com/Okpainmo/rusty-mesh <preferred-mesh-service-name>
cd <preferred-mesh-service-name>Remove the Git history so the mesh service becomes part of the parent project:
rm -rf .gitKeep the runtime files that make Rusty Mesh a service:
src/
config/
Cargo.toml
Cargo.lock
Dockerfile
.dockerignore
.env.sample
.env.development.sample
.env.staging.sample
.env.production.sample
Keep .cargo/config.toml only if you want the local cargo dev watch alias inside the parent
workspace.
Remove repository-only or demo-only files if your parent project already owns those concerns:
rm -rf \
.github \
.husky \
.codex \
.vscode \
demo-microservices \
CHANGELOG.md \
CODE_OF_CONDUCT.md \
CONTRIBUTING.md \
SECURITY.md \
commitlint.config.mjs \
package.json \
bun.lock \
prettier.config.mjs \
.prettierignore \
.editorconfigYou can also remove README.md and LICENSE if the parent repository already provides project-wide
documentation and licensing. Keep them if the mesh service should remain documented as its own
standalone unit inside the parent repo.
Even inside a broader microservice project, keep Rusty Mesh configured as an independent service.
Set its own .env or deployment environment values from the samples, especially
APP__SECURITY__MESH_TOKEN. Every internal service that registers with Rusty Mesh should receive
the matching client-side token and use it when calling registry routes:
Authorization: Bearer <shared-mesh-token>
x-mesh-advertise-host: <reachable-service-host>The parent Compose, Kubernetes, or deployment system should start Rusty Mesh before or alongside
services that depend on discovery. /api/v1/mesh/health stays public for health checks, while all
/api/v1/mesh/services... routes require the shared mesh token.
All endpoints are nested under:
/api/v1/mesh
| Method | Path | Purpose |
|---|---|---|
| GET | / |
Show a short mesh welcome/status message |
| GET | /health |
Check service health |
| GET | /services |
List active service instances |
| POST | /services |
Register or refresh an instance |
| POST | /services/heartbeat |
Update instance lease TTL |
| DELETE | /services |
Unregister an instance |
| GET | /services/{service_name}/{service_version} |
Find a compatible instance with round-robin load balancing |
| GET | /services/{service_name}/{service_version}/{service_port} |
Find a compatible instance on a specific port |
/health is public. All /services routes require the shared mesh token.
Postman collections are available in the postman directory. Import them separately when you want to exercise the mesh API or the demo services without rebuilding requests by hand.
| Collection | File | Folders |
|---|---|---|
mesh-core |
postman/mesh-core.postman_collection.json | health, registry |
demo-microservices |
postman/demo-microservices.postman_collection.json | cart, catalog, order, user |
The mesh-core collection contains:
health: welcome and health-check endpoints.registry: registration, heartbeat, list, discovery, internal-scope discovery, and unregistration endpoints.
Before running mesh-core requests, update these collection variables for your environment:
| Variable | Purpose | Default |
|---|---|---|
mesh_core_base_url |
Rusty Mesh API base URL | http://127.0.0.1:3080/api/v1/mesh |
mesh_token |
Shared token for protected registry routes | local-demo-mesh-token |
service_name |
Service name used in registry examples | orders |
service_version |
Exact service version used for registration | 1.2.3 |
service_version_requirement |
Encoded semver requirement for discovery | %5E1.0.0 |
internal_host |
Internal service host/IP | 10.0.0.20 |
internal_port |
Internal service port | 3000 |
external_host |
Public service host/IP | orders.example.com |
external_port |
Public service port | 443 |
external_scheme |
Public service URL scheme | https |
container_id |
Optional Docker container id for resolution | empty |
The demo-microservices collection contains:
cart: welcome, health, cart feedback, and order-service call endpoints.catalog: welcome, health, catalog feedback, and cart-service call endpoints.order: welcome, health, order feedback, and user-service call endpoints.user: welcome, health, user feedback, and catalog-service call endpoints.
Before running demo-microservices requests, update these collection variables:
| Variable | Purpose | Default |
|---|---|---|
cart_service_base_url |
Cart demo service URL | http://127.0.0.1:30302 |
catalog_service_base_url |
Catalog demo service URL | http://127.0.0.1:30303 |
order_service_base_url |
Order demo service URL | http://127.0.0.1:30304 |
user_service_base_url |
User demo service URL | http://127.0.0.1:30301 |
curl -X POST \
-H "authorization: Bearer ${MESH_TOKEN}" \
-H "x-mesh-advertise-host: 10.0.0.20" \
-H "content-type: application/json" \
-d '{
"service_name": "orders",
"service_version": "1.2.3",
"service_ip": "10.0.0.20",
"service_port": 3000,
"external_host": "orders.example.com",
"external_port": 443,
"external_scheme": "https"
}' \
http://127.0.0.1:3080/api/v1/mesh/servicesResponse:
{
"response_message": "Service registered successfully",
"response": {
"service_name": "orders",
"service_version": "1.2.3",
"ip": "orders.example.com",
"port": 443,
"internal_ip": "10.0.0.20",
"internal_port": 3000,
"url": "https://orders.example.com:443"
},
"error": null
}The external fields are optional. Use them when the service already knows its externally reachable
endpoint. If APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=docker is enabled and no explicit
external endpoint is supplied, Rusty Mesh tries to resolve the external port from Docker instead.
Calling the same endpoint again refreshes the service timestamp. Alternatively, you can use the explicit heartbeat endpoint:
curl -X POST \
-H "authorization: Bearer ${MESH_TOKEN}" \
-H "content-type: application/json" \
-d '{
"service_name": "orders",
"service_version": "1.2.3",
"service_ip": "10.0.0.20",
"service_port": 3000
}' \
http://127.0.0.1:3080/api/v1/mesh/services/heartbeatResponse:
{
"response_message": "Service heartbeat refreshed successfully",
"response": {
"service_name": "orders",
"service_version": "1.2.3",
"ip": "orders.example.com",
"port": 443,
"internal_ip": "10.0.0.20",
"internal_port": 3000,
"url": "https://orders.example.com:443"
},
"error": null
}Heartbeat Identity Matching: The heartbeat endpoint supports flexible lookup. It will match the instance by its Internal Identity (name, version, IP, and port) or by its External Identity (matching against the
external_hostandexternal_portused during registration). The heartbeat response returns the refreshed instance with the same externalip,port, andurlfields used by registration and public discovery, plusinternal_ipandinternal_portfor in-network calls.
Production service clients should call this endpoint on the configured heartbeat interval. With the
default policy, each service instance should refresh every 5 seconds and expires if it has not
refreshed within 15 seconds.
Semantic-version requirements are supported through the semver crate. Because characters such as
^ are special in URLs, encode them in request paths.
curl -H "authorization: Bearer ${MESH_TOKEN}" \
http://127.0.0.1:3080/api/v1/mesh/services/orders/%5E1.0.0Response:
{
"response_message": "Service found successfully",
"response": {
"name": "orders",
"version": "1.2.3",
"ip": "orders.example.com",
"port": 443,
"internal_ip": "10.0.0.20",
"internal_port": 3000,
"timestamp": 1790745600,
"url": "https://orders.example.com:443"
},
"error": null
}For service-to-service calls that should stay on the private network, send
x-mesh-endpoint-scope: internal. In that mode, discovery returns the raw registered instance, so
ip and port are the internal registered endpoint and any resolved external endpoint remains in
the optional external_ip, external_port, and external_scheme fields.
When multiple active instances match, Rusty Mesh sorts the candidates by name, version, IP address, and port using the registered internal endpoint, then returns them in round-robin order on repeated requests.
The port-specific lookup targets the external port when a service has an external endpoint. This is important when multiple replicas share the same internal port but publish to different host ports. If a service has no external endpoint, Rusty Mesh falls back to matching its internal registered port.
curl -H "authorization: Bearer ${MESH_TOKEN}" \
http://127.0.0.1:3080/api/v1/mesh/services/orders/%5E1.0.0/443If no compatible service is found:
{
"response_message": "No matching service found.",
"response": null,
"error": {
"message": "No matching service found.",
"code": "SERVICE_NOT_FOUND"
}
}curl -H "authorization: Bearer ${MESH_TOKEN}" \
http://127.0.0.1:3080/api/v1/mesh/servicesResponse:
{
"response_message": "Services listed successfully",
"response": {
"services": [
{
"name": "orders",
"version": "1.2.3",
"ip": "orders.example.com",
"port": 443,
"internal_ip": "10.0.0.20",
"internal_port": 3000,
"timestamp": 1790745600,
"url": "https://orders.example.com:443"
}
],
"services-count": 1
},
"error": null
}curl -X DELETE \
-H "authorization: Bearer ${MESH_TOKEN}" \
-H "x-mesh-advertise-host: 10.0.0.20" \
-H "content-type: application/json" \
-d '{
"service_name": "orders",
"service_version": "1.2.3",
"service_port": 3000
}' \
http://127.0.0.1:3080/api/v1/mesh/servicesResponse:
{
"response_message": "Service unregistered successfully",
"response": {
"service_name": "orders",
"service_version": "1.2.3",
"ip": "orders.example.com",
"port": 443,
"internal_ip": "10.0.0.20",
"internal_port": 3000,
"url": "https://orders.example.com:443"
},
"error": null
}If the service instance is not registered, Rusty Mesh returns HTTP 404:
{
"response_message": "Service instance is not registered.",
"response": null,
"error": {
"message": "Service instance is not registered.",
"code": "SERVICE_NOT_REGISTERED"
}
}Rusty Mesh accepts exact semantic versions during registration:
1.2.3
Discovery accepts semantic-version requirements:
1.2.3
^1.0.0
~1.2.0
>=1.0.0,<2.0.0
When multiple instances match a load-balanced discovery request, Rusty Mesh sorts the candidates and returns them in round-robin order. This gives callers a predictable service-side balancing pattern across compatible instances.
All environment variables files are loaded before configuration is deserialized:
-
.env- in which the current working environment is selected - as earlier described. -
.env.{APP__DEPLOY__ENV}, for example.env.development
The config loader then resolves application configuration in this order, from lowest to highest priority:
config/base.tomlconfig/{APP__ENV}.tomlconfig/local.toml, if presentAPP__environment variables
Default values live in config/base.toml.
| Variable | Purpose | Default |
|---|---|---|
APP__ENV |
Selects the config environment | required |
APP__SERVER__HOST |
Server bind host | 127.0.0.1 |
APP__SERVER__PORT |
Server bind port | 3080 |
APP__SERVER__REQUEST_TIMEOUT_SECS |
Request timeout in seconds | 60 |
APP__REGISTRY__HEARTBEAT_INTERVAL_SECS |
Expected service heartbeat interval | 5 |
APP__REGISTRY__SERVICE_TTL_SECS |
Service registration TTL | 15 |
APP__REGISTRY__PUBLIC_HOST |
Host used when Docker publishes to wildcard IPs | empty |
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION |
External endpoint resolver: none or docker |
none |
APP__SECURITY__REQUIRE_MESH_TOKEN |
Require token on registry routes | true |
APP__SECURITY__MESH_TOKEN |
Shared registry access token | env override |
APP__APP__NAME |
Service name in health response | mesh_service |
Example:
APP__ENV=development \
APP__SECURITY__MESH_TOKEN=replace-with-a-strong-token \
APP__REGISTRY__HEARTBEAT_INTERVAL_SECS=10 \
APP__REGISTRY__SERVICE_TTL_SECS=30 \
APP__REGISTRY__EXTERNAL_ENDPOINT_RESOLUTION=none \
cargo runSet APP__SECURITY__REQUIRE_MESH_TOKEN=false only for isolated local debugging. Production and
shared environments should keep token enforcement enabled and provide a strong secret through the
active environment file.
The heartbeat interval must be lower than the TTL. For example, a 10 second heartbeat with a 30
second TTL gives each service roughly three heartbeat opportunities before it is removed from
discovery.
Rusty Mesh includes a k6 traffic simulation script at:
k6-traffic-simulation/main.js
The script checks public health, registers one unique service instance per virtual user, and rotates through heartbeat, list, discovery, internal-scope discovery, exact external-port discovery, and unregister cleanup. Use k6-traffic-simulation/.env.sample as the template for local k6-only environment values.
Create a local k6 environment file from the template:
cp k6-traffic-simulation/.env.sample k6-traffic-simulation/.envEdit k6-traffic-simulation/.env, then source it and run the simulation:
set -a
. ./k6-traffic-simulation/.env
set +a
k6 run k6-traffic-simulation/main.jsSee k6-traffic-simulation/README.md for environment-loading
details. The k6 script does not automatically read the app's root .env; source the dedicated
k6-traffic-simulation/.env file before running it.
Format the code:
cargo fmtRun tests:
cargo testRun a formatter check:
cargo fmt --checkThe test suite covers:
- Registering a service.
- Refreshing an existing service lease through heartbeat.
- Finding a compatible semantic version.
- Unregistering a service.
- Returning
404when unregistering a service instance that does not exist. - Cleaning up expired services.
- Rejecting invalid service versions.
- Rejecting missing or invalid mesh authentication tokens on registry routes.
- Exercising the HTTP health, register, heartbeat, find, and unregister routes.
Run all tests:
cargo test-
Registry state is in-memory and is lost when the process restarts. This design is intentional as it keeps the system simple, focused, highly performant, and flexible enough to permit customized scaling/extending. A reasonable area(in terms of extending the current system) that comes to mind is adding data persistence via a queue(background jobs), which will be triggered after every successful service registration/de-registration.
-
There is no multi-node replication. As it stands, deploying multiple instances of Rusty Mesh remains to be handled as you see fit. A very good way to utilize Rusty Mesh, will be to treat it's deployment as
pods- similar to Kubernetes. With each pod consisting of a Rusty Mesh copy, andpodlets- other non-mesh services. Of course, this does not prevent individual service scaling for cases where only specificpodletsshould be added for load balancing. -
Registry routes are protected by a shared mesh token. This is a lightweight service-to-service boundary, not per-service identity, RBAC, mTLS, or end-user authorization.
-
Keep
APP__SECURITY__REQUIRE_MESH_TOKEN=trueoutside isolated local debugging, and setAPP__SECURITY__MESH_TOKENfrom the active environment file or deployment secret store. -
The health endpoint is intentionally public for container health checks and load balancers.
-
Service advertised-host detection prefers
x-mesh-advertise-host, falls back tox-forwarded-for, and finally uses localhost.
These constraints define the first production-facing shape of the service. They keep the registry straightforward to operate while leaving a clear path toward persistent storage, replication, service identity, mTLS, and richer mesh routing layers - as the case may be with your needs.
Rusty Mesh is licensed under the MIT License.