Skip to content

Capability matrix

This matrix covers two backend implementations: C# on ASP.NET Core, and Kotlin and Java on Spring Boot. Use this page to check whether a capability exists in the language you work in before you design around it.

Each cell was checked against that implementation’s source, public API, and tests, not against its documentation. A cell says a capability exists. It does not say the two implementations behave identically: where both have a capability but it differs on the wire, where the implementations differ describes the difference. The Kotlin and Java evidence behind every row, including which test proves it, is in the JVM parity reference.

StatusMeaning
ImplementedThe capability exists in the current source and public API and is usable from this language.
PartialUsable, with the boundary stated in the notes.
Not plannedAbsent from source, and recorded as not planned for that implementation.
Not applicableThe capability belongs to another platform’s host or toolchain.

A capability one implementation has and the other has neither built nor ruled out is not forced into these states. It is listed under not yet in every implementation.

Kotlin and Java share one runtime. The Java column counts capabilities usable through Java-callable APIs; language-specific verification limits are stated separately. Java uses annotations on Java types, CompletionStage and Flow.Publisher returns, static query methods, and the Blocking* and Async* contracts rather than implementing suspending methods.

Not every Java contract is discovered the same way:

  • Collected as Spring beans directly: AsyncAuthenticationHandler, AsyncIdentityDetailsProvider, AsyncUsersProvider, AsyncTenantsProvider, ConceptValidator, and BlockingQueryRendererFor, BlockingReadModelInterceptor, BlockingObservableQueryEmissionGuard, and BlockingReadModelForCommandResolver, which extend the Kotlin contracts.
  • Run only through an adapter bean you declare: command and query filters, authorization filters and named policies, command and query validators, command execution scopes, and command response value handlers. Wrap the Java implementation in the matching Blocking*Adapter or Async*Adapter from io.cratis.arc.java and return it from a @Bean method. A class that implements BlockingCommandFilter without that bean is never called. See pipeline filters.
CapabilityC#KotlinJavaNotes
Model-bound commandsImplementedImplementedImplementedA command type with a Handle/handle method. C# · Kotlin and Java
Asynchronous handlersImplementedImplementedImplementedC# Task/ValueTask, Kotlin suspend, Java CompletionStage.
Provided valuesImplementedImplementedImplementedProvide/provide loads data after filters pass and hands it to the handler. C# · Kotlin and Java
Command keysImplementedImplementedImplementedC# ICanProvideKeyForCommand; JVM @CommandKey and CommandKeyProvider. C# · Kotlin and Java
Several return valuesImplementedImplementedImplementedC# tuples; JVM Pair, Triple, CommandProvidedValues, and CommandResponseValues. Exactly one value may reach the client on the JVM. C#
Alternative return valuesImplementedImplementedImplementedC# OneOf values; JVM ArcOneOf. Java can build an ArcOneOf through its static of and alternative factories, but no Java-authored test returns one. Generating named union types (@GenerateOneOf) is not planned on the JVM.
Response value handlersImplementedImplementedImplementedJava needs an adapter bean. C#
Validate without executingImplementedImplementedImplementedPOST <command-route>/validate. C# · Kotlin and Java
Command filtersImplementedImplementedImplementedJava needs an adapter bean. C# · Kotlin and Java
Command execution scopesImplementedImplementedImplementedJava needs an adapter bean. C# · Kotlin and Java
Calling the pipelines from codeImplementedImplementedImplementedJava uses BlockingCommandPipeline, BlockingQueryPipeline, and JavaAsyncScope; blocking calls need explicit per-call or constructor-bound options. C# · Java
Controller-based commands and queriesImplementedNot plannedNot plannedThe JVM generates model-bound Spring MVC endpoints only. C#
CapabilityC#KotlinJavaNotes
Model-bound queriesImplementedImplementedImplementedStatic methods on a read model; Kotlin uses @JvmStatic companion methods. C# · Kotlin and Java
HTTP QUERY methodImplementedImplementedImplementedC# · Kotlin and Java
Observable queriesImplementedImplementedImplementedC# ISubject<T>/IObservable<T>; Kotlin Flow/StateFlow; Java Flow.Publisher and ObservableState. C# · Kotlin and Java
Observable transportsImplementedImplementedImplementedHTTP snapshot, direct SSE and WebSocket, and the multiplexed hubs. The JVM transport code is shared; its SSE and WebSocket runtime tests run against the Kotlin sample. Snapshot readiness differs; see the HTTP contract.
Paging and sortingImplementedImplementedImplementedThe result shapes that get paged differ. C# pages and sorts an IQueryable result through QueryableQueryRenderer. The JVM’s default fallback pages and sorts Iterable results in memory when no custom renderer matches; custom renderers own their paging and sorting. QueryPage and Spring Data Page results pass through; a returned array is not sorted or paged, and its paging totals stay at zero. C# · Kotlin and Java
Query filtersImplementedImplementedImplementedJava needs an adapter bean. C# · Kotlin and Java
Renderers, read-model interceptors, and emission guardsImplementedImplementedImplementedC# · Kotlin and Java
Services in query methodsImplementedImplementedImplementedService parameters are injected and never become client arguments. C# · Kotlin and Java
Spring Data Pageable, Sort, and PageNot applicableImplementedImplementedKotlin and Java
Query health endpointImplementedImplementedImplemented/.cratis/queries/health. Its authentication differs; see the HTTP contract. C#
CapabilityC#KotlinJavaNotes
Command and query validatorsImplementedImplementedImplementedJava needs an adapter bean. C# · Kotlin and Java
Validation severityImplementedImplementedImplementedWarnings and information alongside errors, and treating warnings as errors. C# · Kotlin and Java
Concept validatorsImplementedImplementedImplementedOne rule for a concept, applied wherever the concept appears. C# · Kotlin and Java
Annotation rules in generated proxiesImplementedImplementedImplementedC# DataAnnotations; JVM Jakarta Bean Validation, which covers more annotations. C# · Kotlin and Java
Validator rules shared with the clientImplementedImplementedImplementedEach side sends only the rules it recognizes. C# extracts the FluentValidation rules its proxy generator knows; the JVM FluentModelValidator<T> supports thirteen literal rules and no warning severity. C# · Kotlin and Java
Opting one member out of validationPartialImplementedImplementedC# [IgnoreValidation] applies to a controller class or action, not to a model-bound artifact or one member; one member can skip concept validators with IgnoreConceptRules(). JVM @IgnoreValidation skips one member and everything below it. Kotlin and Java
CapabilityC#KotlinJavaNotes
Anonymous, authenticated, and role authorizationImplementedImplementedImplementedAn operation’s own declaration replaces its type’s. C# · Kotlin and Java
Named policies and authentication schemesImplementedImplementedImplementedC# runs scoped asynchronous native policies on either host and ASP.NET Core policies on that host. Actual scheme authentication requires ASP.NET Core and an Arc-owned execution scope; standalone Core rejects scheme requirements. The JVM checks the caller’s already-captured scheme rather than authenticating another scheme. Java policies need an adapter bean. C# policies · C# scheme boundaries · Kotlin and Java
Authentication handlersImplementedImplementedImplementedJava implements AsyncAuthenticationHandler. C# · Kotlin and Java
Identity details and /.cratis/meImplementedImplementedImplementedC# · Kotlin and Java
Microsoft identity platform headersImplementedImplementedImplementedx-ms-client-principal. Ignored on C# until the host sets TrustForwardedIdentityHeaders. Off by default on the JVM; enabling it also requires an application ArcPlatformIdentityTrust bean because the default trusts no request. C# · Kotlin and Java
Development users and tenantsImplementedImplementedImplemented/.cratis/users and /.cratis/tenants. C# · Kotlin and Java
Tenant resolutionImplementedImplementedImplementedFixed, header, query string, claim, subdomain, and development resolvers. Enforcement differs; see the HTTP contract. C# · Kotlin and Java
CapabilityC#KotlinJavaNotes
MongoDBImplementedImplementedImplementedC# Cratis.Arc.MongoDB; JVM Spring Data MongoDB. C# · Kotlin and Java
Relational databasesImplementedImplementedImplementedC# Entity Framework Core; JVM Spring Data JPA. C# · Kotlin and Java
Observable queries from database changesImplementedImplementedImplementedC# observes MongoDB collections and EF Core sets. The JVM uses MongoDB change streams, which need a replica set or sharded cluster, and explicit in-process JPA notifications. C# · Kotlin and Java
Read models in command handlersImplementedImplementedImplementedArc resolves a read model by command key and hands it to the handler. C# · Kotlin and Java
CapabilityC#KotlinJavaNotes
Events returned from commandsImplementedImplementedImplementedAppended only when the command succeeds. C# · Kotlin and Java
Concurrency scopesImplementedImplementedImplementedC# · Kotlin and Java
Chronicle read models in commands and queriesImplementedImplementedImplementedC# · Kotlin and Java
Commands from reactorsImplementedImplementedImplementedBoth let a reactor declare the system roles its commands run with through ExecuteCommandsAsSystem. A JVM reactor hands command values to ChronicleCommandSideEffectHandler. C# · Kotlin and Java
Chronicle command scenariosImplementedImplementedImplementedAn in-memory event log; no Chronicle kernel runs. C# · Kotlin and Java
CapabilityC#KotlinJavaNotes
In-process scenariosPartialImplementedImplementedC# has command and snapshot query scenarios, but no observable-query scenario. The JVM has command, query, and observable query scenarios; Java uses the Blocking* and Async* scenario classes. C# commands · C# queries · Kotlin and Java
CapabilityC#KotlinJavaNotes
TypeScript proxies for commands and queriesImplementedImplementedImplementedC# · Kotlin and Java
TypeScript proxies for observable queriesImplementedImplementedImplementedC# · Kotlin and Java
ConceptsImplementedImplementedImplementedConceptAs<T> crosses the wire as its underlying value. C# · Kotlin and Java
Polymorphic derived typesImplementedImplementedImplementedA _derivedTypeId discriminator. A JVM hierarchy that arrives only as a dependency binary needs a DerivedTypeRegistrar. Kotlin and Java
DateOnly, TimeOnly, and Guid in proxiesImplementedImplementedImplementedJVM Duration is ISO-8601 text, not TimeSpan. C# · Kotlin and Java
Documentation comments in proxiesImplementedImplementedImplementedC# XML documentation; Kotlin KDoc; Java Javadoc. Which declarations each side documents has not been compared.
Mapping types to TypeScript packagesImplementedImplementedImplementedC# maps by assembly and by type; the JVM maps by package and by type. C# · Kotlin and Java
Types outside commands and queriesImplementedImplementedImplementedC# library mode; JVM @ExportedType and identity details roots. C# · Kotlin and Java
Build-time diagnosticsImplementedImplementedImplementedC# Roslyn analyzers; JVM KSP diagnostics, which also cover Java sources. C# · Kotlin and Java
OpenAPIImplementedImplementedImplementedC# · Kotlin and Java
Introspection endpointsImplementedImplementedImplemented/.cratis/commands and /.cratis/queries. Metadata depth differs; see the HTTP contract. C#
Screenplay generationImplementedNot plannedNot plannedC#
CapabilityC#KotlinJavaNotes
ASP.NET Core hostImplementedNot applicableNot applicableC#
Spring Boot hostNot applicableImplementedImplementedKotlin and Java
Standalone HTTP host outside ASP.NET Core or Spring BootImplementedNot plannedNot plannedC# ArcApplication. C#
Static files and SPA fallbackImplementedNot plannedNot plannedSpring Boot serves static resources itself. C#
[FromRequest] bindingImplementedNot plannedNot plannedC#
Opting a type out of auto-registrationImplementedNot applicableNot applicableC# [IgnoreAutoRegistration] excludes a DbContext from Entity Framework Core hookup. JVM entry points are opt-in annotations. C#
Correlation IDsImplementedImplementedImplementedX-Correlation-ID on every request. Edge cases differ; see the HTTP contract.
ObservabilityImplementedImplementedImplementedC# ActivitySource tracing; JVM Micrometer observations. C# · Kotlin and Java

These C# capabilities have no Kotlin or Java counterpart in source, and no decision records them as not planned for the JVM. They are listed here rather than marked not planned.

CapabilityAvailable inKotlin and Java
Command operationsC#Not in source; no decision recorded.
Aggregate rootsC#Not in source; no decision recorded.

The JVM parity reference also tracks rows that describe how the JVM is verified rather than a capability you adopt: the proxy differential gates, the runtime and HTTP conformance gates, binary compatibility, runtime hardening, Kotlin ergonomics, and the Java adapters themselves. It records cross-store transactions as not planned; neither implementation provides one. Admission control and request limits are compared in the HTTP contract.