Simple and easy compile-time JVM framework for Java & Kotlin.
Explicit code, strong types, precise compiler feedback, and no runtime magic.
Documentation · Getting Started · Examples · Kora Skills
🇷🇺 Русская версия: README.ru.md
Kora is a full-stack, cloud-oriented server framework for Java and Kotlin. You write familiar, high-level declarative code — controllers, repositories, listeners, config — and Kora's annotation processor turns it into ordinary, readable Java/Kotlin at compile time: the dependency graph, HTTP routing, repository implementations, and aspect wrappers are all generated source you can open and read.
The result is a stack that is fast for the machine and transparent for the human — and, for the same reasons, unusually easy for AI coding agents to reason about.
Your code + annotations
│ compile
▼
Annotation Processor / KSP → generated graph, routes, repositories, aspects
│ run
▼
A running service — no runtime reflection, no dynamic proxies, no classpath scanning
- Simplicity — one recommended, well-supported way to solve each problem instead of five competing styles. Familiar Java/Kotlin idioms, thin abstractions, and generated code you can step through — so onboarding is fast and context lives in the code, not in framework folklore.
- Transparency — Kora generates human-readable source with explicit graphs and free aspects. What you read is what runs — no black box. Compile-time checks turn missing or ambiguous wiring, and even wrong SQL placeholders, into readable compiler errors instead of 3 a.m. stack traces.
- Efficiency — the dependency container is built at compile time and initialized as parallel as possible, so services start in seconds, not tens of seconds and reach peak throughput without a long, expensive JIT warm-up. Faster readiness makes horizontal scaling cheaper and rolling deploys smoother.
- Performance — high-performant code generated at compile time. No runtime Reflection API, no dynamic proxies, thin fine-grained abstractions and free aspects, and only the most efficient module implementations. Top-tier TechEmpower results out of the box, with nothing to tune.
Throughput — external TechEmpower measurement (single query, higher is better):
Startup & readiness — 10× PetClinic (ten times the controllers, repositories and services of the classic Spring PetClinic, with full production metrics, tracing, logs and probes) in a container on 1 CPU / 1 GB, lower is better:
| Framework | Time to serve traffic |
|---|---|
| Kora | ~4.9 s |
| Spring (heavily optimized) | ~21.1 s |
| Spring (stock) | ~26.5 s |
Build time — clean artifact build of the same 10× PetClinic, average of 5 runs on a MacBook Pro 2019 (i7-9750H):
| Build | Time |
|---|---|
Kora — ./gradlew clean distTar |
~11.6 s |
Spring — bootJar, stock |
~9.3 s |
Spring — bootJar, optimized (layered jar + AOT) |
~18.7 s |
Honest note: against stock Spring, build times are comparable (Kora is even slightly slower). But Spring's fast startup requires a layered jar + AOT that roughly doubles its build time — Kora builds ~1.6× faster than optimized Spring and gets the fast startup for free.
Declare the application graph and a controller — plain Java that reads like plain Java:
@KoraApp
public interface Application extends
HoconConfigModule,
JsonModule,
LogbackModule,
UndertowHttpServerModule {
static void main(String[] args) {
KoraApplication.run(ApplicationGraph::graph);
}
}
@Component
@HttpController
public final class HelloController {
@HttpRoute(method = HttpMethod.GET, path = "/hello")
HttpServerResponse hello() {
return HttpServerResponse.of(200, HttpBody.plaintext("Hello, Kora!"));
}
}ApplicationGraph is generated at compile time — run ./gradlew classes and open it under build/generated/… to see exactly how components are created and wired. The same is true for Kotlin, using
KSP instead of annotation processors.
Install — add the Kora BOM, the HTTP server module (and any others you need), and the annotation processor for Java or KSP for Kotlin. The Getting Started guide has copy-paste Gradle and Maven setup for both languages.
- Declare — controllers, repositories, listeners, config, and resilience policies as constructors, interfaces, and annotations (
@KoraApp,@Component,@Module,@Tag). - Compile — the processor validates the whole graph and generates implementations. A missing or ambiguous dependency, a dependency cycle, or a wrong
@Queryplaceholder fails the build, not production. - Run — what executes is the generated source: no reflection, no dynamic proxies, no classpath scanning. Everything is debuggable and traceable, with thin, honest stack traces.
Because wiring is explicit on @KoraApp and nothing is auto-scanned or silently pulled in, the dependency graph is a single structure you (or a tool) can trace end to end.
Kora ships one carefully chosen, high-performance implementation per problem — enable only the modules your service needs:
- HTTP — server & declarative client, request mapping, interceptors, management endpoints, and strongly typed OpenAPI codegen; SOAP client.
- Data — SQL-first repositories with compile-time-checked
@Query, over JDBC, R2DBC, Vert.x, and Cassandra; column macros, generated mappers, batches, and migrations. - Messaging & RPC — Kafka consumers/producers, gRPC server & client, and an S3 client.
- Aspects — resilience (
@Retry,@Timeout,@CircuitBreaker,@Fallback), caching (Caffeine / Redis), validation, scheduling — generated at compile time, no runtime proxies. - Core — compile-time dependency injection, typed configuration (HOCON / YAML), JSON without reflection, virtual-thread-friendly concurrency.
- Observability — metrics, tracing, structured logging, and probes for every module, following the
OpenTelemetrystandard, plus graceful shutdown — designed in, not bolted on.
@KoraAppTest spins up the real application graph, exactly as in production — and automatically trims it to the @TestComponents you declare and their dependencies, so you test precisely what
you wire, nothing more.
@KoraAppTest(Application.class)
class PetServiceTests {
@Mock
@TestComponent
private PetRepository petRepository; // replace a node with a stub
@TestComponent
private PetService petService; // inject any node from the graph
@Test
void findByID() {
Mockito.when(petRepository.findById(1)).thenReturn(Optional.of(pet));
assertTrue(petService.findByID(1).isPresent());
}
}Fast component tests, integration tests with Testcontainers, and black-box tests against the assembled service all use the same explicit graph.
The qualities that make Kora approachable for a newcomer are the same ones that make it tractable for an AI coding agent:
- No runtime magic to reverse-engineer — generated source is what runs; less reflection and fewer hidden rules mean less context to hold in your head or for a model to guess.
- The compiler as a second reviewer — a fast, strict
change → compile → precise error → fixloop, plus cheap component/integration tests thanks to fast context startup. - Strong typing end to end — from internal contracts to the external API via the OpenAPI generator; a wrong assumption becomes a compile error, not a runtime bug.
- One clear way — a small set of orthogonal abstractions shrinks the space of choices, so a newcomer avoids dead ends and a model avoids mixing incompatible styles.
There is also kora-skills — an official skill that lets your AI agent teach and build Kora straight from the official guides and examples.
- Documentation — English
- Guides — English
- Runnable examples — kora-examples
- AI skill — kora-skills
Issues and pull requests are welcome. Building the project requires JDK 17+ and uses the Gradle wrapper:
./gradlew buildPlease open an issue to discuss changes before submitting a pull request.

