Ørbs & Modules
An Ørb is the top-level application boundary in Orbital. It defines the namespace and structural context in which data, schemas, and processing rules exist.
An Ørb does not represent domain data itself. Instead, it scopes and constrains how data is defined, stored, and interpreted.
Ørbs vs Services
Section titled “Ørbs vs Services”An Ørb is an abstraction on top of one or more microservices. It represents a logical grouping of features and data that is exposed to the platform as a single unit.
Ørbs do not replace services, rather they define how service capabilities are combined, scoped, and presented within Orbital.
Example
Section titled “Example”Consider two Ørbs responsible for account management:
Access— Back Office administrator accountsUsers— Customer user accounts
Both Ørbs rely on the same underlying services:
- the Core Service
- an Auth Service
The Auth Service exposes a shared set of handlers:
/createInvite/createAccount/login/logout
From the perspective of Orbital, these handlers are exposed through Ørb-specific endpoints derived from each Ørb’s configuration:
Access Ørb
/access/createInvite/access/createAccount/access/login/access/logout
Users Ørb
/users/createInvite/users/createAccount/users/login/users/logout
Although the underlying business logic is shared, each Ørb remains isolated. Data is stored in Ørb-dedicated streams, logs are produced in the context of the Ørb, and consumers operate exclusively on Ørb streams, without knowledge of the underlying services.
Ørbs have no direct knowledge of any other Ørb, with the exception of the Registry, which act as a runtime bridge between them.
Standard and Custom Ørbs
Section titled “Standard and Custom Ørbs”Ørbs are classified by how they are implemented:
- Standard Ørbs rely only on Orbital core capabilities
- Custom Ørbs require one or more dedicated services to provide domain-specific logic.
This classification does not affect the structural definition of an Ørb. For the platform, they are just Ørbs.
Responsibilities of an Ørb
Section titled “Responsibilities of an Ørb”An Ørb is responsible for:
- defining a namespace for API endpoints, schemas, and entries
- declaring which Modules exist
- scoping Schemas and Entries and it’s other Messages to a single application context
- isolating data and behavior from other Ørbs
There is no implicit sharing of data or state between Ørbs.
Ørb stream peristance hierarchy
Section titled “Ørb stream peristance hierarchy”The hierarchy of which Ørb, Module, Schema a Message belongs to is derived from the NATS subject:
Entries
Subject: games.catalog.entries.game.cq9k2x4m5n6o7p8q └─┬─┘ └──┬──┘ └──┬──┘ └┬─┘ └───────┬───────┘ orb module role schemaId idSchemas
Subject: games.catalog.schemas.game └─┬─┘ └──┬──┘ └──┬──┘ └┬─┘ orb module role idFrom a Jetstream perspective, all Messages are managed identically.
Modules
Section titled “Modules”A Module is a container that declares which category of Messages it allows.
- each Module allows exactly one Message category
- all Schemas within a Module must conform to that category
- Entries created from those Schemas inherit the same category
- how Schemas are created (manually or generated by services) is Module-specific
Module Types
Section titled “Module Types”Module types are used to declare a specific Message payload structure.
For example, the payload for Messages in a content Module must conform to a very specific content schema, and the payload for rules is following a completely different schema.
config— Managed Messagescontent— Managed Messagesrules— Managed Messagessettings— Declarative Messagestransactions— Transactional Messages
All Messages in a Module Type conforms to exactly one Message category. This ensures lifecycle semantics are explicit and mechanically enforced.
flowchart TD
subgraph Messages["Messages"]
direction TB
%% Level 1
subgraph MessageCategory["Message Category"]
direction LR
declarative["declarative"]
managed["managed"]
transactional["transactional"]
end
%% Level 2
subgraph ModuleType["Module Type"]
direction LR
settings["settings"]
config["config"]
content["content"]
rules["rules"]
transactions["transactions"]
end
%% Level 3 (renamed)
subgraph MessageRole["Message Role"]
direction LR
settings_entries["entries"]
config_schemas["schemas"]
config_entries["entries"]
content_schemas["schemas"]
content_entries["entries"]
rules_entries["entries"]
transactions_schema["schema"]
transactions_entries["entries"]
end
%% Category -> Module Type
declarative --> settings
managed --> config
managed --> content
managed --> rules
transactional --> transactions
%% Module Type -> Message Role
settings --> settings_entries
config --> config_schemas
config --> config_entries
content --> content_schemas
content --> content_entries
rules --> rules_entries
transactions --> transactions_schema
transactions --> transactions_entries
end