Skip to content
Mario edited this page Sep 23, 2026 · 2 revisions

Vyra documentation

Vyra is an asynchronous, type-safe messaging framework for Java. It gives you the ergonomics of a local method call with the semantics of distributed messaging, over whatever broker you choose.

┌─────────────────┐       request("billing", req, ...)       ┌─────────────────┐
│   API Gateway   │ ───────────────────────────────────────▶ │ Billing Service │
│ (Vyra Client A) │ ◀─────────────────────────────────────── │ (Vyra Worker B) │
└─────────────────┘              typed response              └─────────────────┘
         │                                                            ▲
         │             publish("orders", orderEvent)                  │
         └────────────────────────────────────────────────────────────┘

Why Vyra

  • Typed contracts: requests, responses and events are plain Java records. No JSON bodies, no manual casting, no reflection magic.
  • Small API: eight core methods, five builder options. The whole framework fits in an afternoon.
  • Asynchronous: every operation returns a standard CompletionStage.
  • Zero-dependency core: vyra-core has no third-party runtime dependencies. You plug in exactly what you need.
  • Worker load balancing: requests to a service target are distributed across the instances listening on it.
  • Predictable failures: timeouts, error propagation, and delivery guarantees are explicit and documented.

Quick look

Connecting two services looks like this:

// 1. Define immutable records for your wire contract
record GetPlayerRequest(String playerId) {}
record PlayerResponse(String playerId, String name, int score) {}

// 2. Spin up instances (InMemory for local testing, a broker transport in production)
Vyra backend = InMemoryVyra.inMemory().serializer(JacksonSerializer.jackson()).build();
Vyra client  = InMemoryVyra.inMemory().serializer(JacksonSerializer.jackson()).build();

// 3. Register stable message identifiers (these travel on the wire, not class names)
backend.register("player.get", GetPlayerRequest.class);
backend.register("player.info", PlayerResponse.class);
client.register("player.get", GetPlayerRequest.class);
client.register("player.info", PlayerResponse.class);

// 4. Register a request handler (automatically starts listening)
backend.handle("backend", GetPlayerRequest.class, req ->
        CompletableFuture.completedFuture(new PlayerResponse(req.playerId(), "Mario", 1200)));

// 5. Send an asynchronous request with an explicit timeout
client.request("backend", new GetPlayerRequest("p-100"), PlayerResponse.class, Duration.ofSeconds(3))
        .thenAccept(player -> System.out.println("Player: " + player.name() + " (Score: " + player.score() + ")"))
        .exceptionally(err -> {
            System.err.println("Request failed: " + err.getMessage());
            return null;
        });

Documentation

Getting started and messaging patterns

  • Getting started: setting up Vyra, registering message types, implementing request handlers.
  • Request / response: two-way communication, correlation IDs, worker queues, broadcast requests, timeouts.
  • Events: one-way communication, broadcasting, at-most-once delivery.

Transports and formats

  • Transports: Redis in production, in-memory for testing, custom transports.
  • Serialization: Gson, Jackson, Smile, CBOR, and the uniform network constraint.
  • Configuration: node IDs, timeouts, thread pools, builder options.

Inside the framework

Reference

  • FAQ: common questions, answered.
  • Roadmap: what is planned for the next releases and what is not.

Vyra documentation

Getting started and messaging patterns

Transports and formats

Inside the framework

Reference

Clone this wiki locally