Focused Engineering Is Not NIH: Why Kora Builds Only What It Can Own Well¶
August 12, 2026
The accusation of “Not Invented Here” is easy to make against any framework that contains its own dependency injection engine, HTTP abstractions, repository generator, AOP implementation, OpenAPI generator, resilience components, scheduling infrastructure, or specialized runtime pieces. If a mature external library already exists somewhere in the JVM ecosystem, why not simply depend on it? Why build anything inside the framework at all? That question is useful, but only if it is asked precisely. NIH is not the act of writing software internally. If it were, every framework, database, compiler, operating system, and platform would be guilty by definition. NIH is a decision-making failure: rejecting mature external solutions primarily because they were not created inside the organization, even when those external solutions fit the requirements well and integrating them would be cheaper, safer, and more maintainable than replacing them.
The Kora Framework’s architecture points in a much narrower direction. It does not try to rewrite the world around itself. It integrates mature technologies such as JDBC, Kafka, gRPC, OpenTelemetry, Micrometer, Undertow, database drivers, cloud-native standards, and ordinary JVM libraries. At the same time, it deliberately owns a smaller set of framework-native components where owning the implementation allows Kora to enforce properties end to end: compile-time generation, strong typing, predictable behavior, low runtime overhead, transparent generated source, a coherent configuration model, and consistent telemetry. That leads to the central thesis:
Not every in-house component is NIH. NIH is rejecting mature external solutions without a good reason. Kora’s model is narrower: reuse proven technologies where they fit, and build framework-native components only where tight integration, performance, compile-time guarantees, or simplicity justify it.
The right question is therefore not simply:
“Why is this implemented inside the framework?”
A better question is:
“What does a framework-specific implementation provide that another adapter layer over an external tool would not?”
That question forces a real engineering comparison. Sometimes the answer will be “very little,” in which case Kora should reuse the mature external solution. Sometimes the answer will be “compile-time contracts, lower semantic distance, generated source, fewer runtime layers, better performance, and a unified application model,” in which case specialization can be entirely rational. The distinction can be summarized simply:
Reuse when a mature solution fits
↓
JDBC / Kafka / gRPC / OpenTelemetry / JVM libraries / vendor SDKs
Build when integration itself is the product
↓
compile-time generators
framework-native adapters
specialized runtime pieces
The difficult engineering work is deciding which side of that boundary a capability belongs on.
NIH Is About Motivation, Not Code Ownership¶
The term NIH is frequently used too broadly. A team writes a small parser, and somebody calls it NIH. A framework implements a scheduler, and somebody calls it NIH. An organization builds a specialized client wrapper, and somebody calls it NIH. This reduces a useful architectural warning into a slogan.
The actual problem with NIH is not that software is implemented locally. The problem is unjustified duplication combined with ecosystem distrust. If a mature external library already solves the problem, has a strong maintainer base, good performance, a stable API, and a good fit with the architecture, replacing it merely because the team prefers to control everything is usually a bad trade. The team inherits implementation cost, testing cost, security responsibility, maintenance burden, and compatibility risk without receiving a meaningful architectural benefit.
But specialization is different. Sometimes the integration itself is what the framework is trying to optimize. A generic external library may be excellent at the underlying task while still requiring runtime reflection, adapters, generic configuration, or abstractions that conflict with the framework’s model. In that case, a framework-native implementation can reduce total complexity rather than increase it. The key is whether local ownership buys a property the framework actually cares about.
Kora Does Not Try to Rewrite Its Dependencies¶
The easiest way to test the NIH accusation is to inspect what Kora already reuses. Kora does not ship its own relational database. It works with JDBC and real database drivers. It does not reinvent Kafka. It integrates Apache Kafka and keeps Kafka’s model visible. It does not invent a replacement RPC protocol; it works with gRPC. It does not create a proprietary observability standard; it integrates OpenTelemetry and Micrometer. Its HTTP server stack builds on a real high-performance web server rather than inventing a new TCP stack. Its applications use ordinary Java and Kotlin tooling, Gradle, JUnit, Testcontainers, and the standard JVM ecosystem.
This is not the behavior of a project philosophically committed to “we must own everything.” The actual pattern is closer to:
Use the ecosystem for technologies that are already solved well.
Own framework behavior where the framework can materially improve the model.
That distinction is visible in Kora’s own stated philosophy. The framework explicitly says it does not pursue breadth for its own sake, does not wrap every possible technology behind a framework-specific abstraction, and allows applications to replace or customize components and add their own integrations through the same application model. That is a much more selective strategy than NIH.
JDBC Is a Good Example of Reuse¶
Kora repositories are framework-native, but the underlying database technology is not. A Kora JDBC repository can generate the repetitive implementation around SQL, parameter binding, result mapping, telemetry, and connection handling. Yet the developer still reasons about JDBC and the database. SQL remains SQL. Connection pools remain connection pools. Transactions retain database semantics. PostgreSQL remains PostgreSQL.
The framework owns the integration boundary because code generation can provide value there. It does not replace the database ecosystem. That is an important distinction. Kora’s own repository layer is not evidence that it distrusts JDBC; it is evidence that JDBC is low-level enough that generating the repetitive glue around it can produce a better application programming model while preserving the underlying technology. The architecture looks like:
The framework-specific part is the generated glue, not the database semantics.
Kafka Is Reused Rather Than Reimagined¶
The same logic appears in messaging. Kora can manage configuration, lifecycle, telemetry, and application wiring around Kafka, but the developer still deals with Kafka concepts: topics, partitions, consumer groups, records, offsets, serialization, rebalance, and acknowledgement behavior. That means the massive Kafka ecosystem remains applicable. Operational documentation remains useful. Broker tooling remains useful. Existing Kafka expertise transfers directly. A true NIH approach would be more likely to hide Kafka behind a proprietary messaging universe and ask users to learn the framework’s own model first. Kora’s thin-integration philosophy points in the opposite direction.
gRPC Remains gRPC¶
Kora similarly has no need to replace protobuf, grpc-java, generated stubs, deadlines, streaming semantics, status codes, and interceptors with its own RPC worldview. The framework can integrate
gRPC into dependency injection, configuration, lifecycle, and telemetry while allowing the real protocol and library model to remain visible. This is exactly what “reuse where the mature solution
fits” should look like. The framework adds value where it has context that gRPC itself does not have: application composition, component lifecycle, configuration conventions, and cross-module
observability. It does not rewrite the protocol.
OpenTelemetry Is Reused as a Standard¶
Observability makes the anti-NIH pattern especially obvious. Kora does not invent a private metrics and tracing standard simply because it wants coherent telemetry. Instead, it uses OpenTelemetry-oriented semantics and Micrometer integration across modules. Kora can standardize how telemetry is attached to HTTP, database, Kafka, gRPC, scheduling, caching, and other framework components without requiring operators to adopt a proprietary observability universe. This is a strong form of reuse: Kora owns the integration policy while the telemetry standard remains external and interoperable.
The Framework Should Own What Requires Framework Context¶
Why, then, implement anything inside Kora? Because some capabilities are impossible to optimize deeply if the framework treats them as opaque external boxes. Dependency injection is the clearest example. Kora’s compile-time graph is foundational to initialization, lifecycle, component replacement, compile-time validation, generated code, and startup behavior. Replacing that with a runtime-oriented external DI container would not be “more ecosystem friendly” if doing so destroyed the properties Kora exists to provide. The framework’s own DI system allows it to know, at compile time, which components exist, how they depend on one another, where cycles occur, which implementation satisfies a dependency, how initialization can be parallelized, and which generated code needs to be compiled. That information becomes part of the architecture rather than an opaque runtime container. Owning this component is therefore not duplication for duplication’s sake. It is how Kora enforces its central design.
Integration Itself Can Be the Product¶
This is the most useful way to understand Kora’s custom components. Sometimes the underlying technology already exists, but the integration requirements are the part Kora wants to optimize. Consider mapping, repositories, declarative HTTP clients, AOP, or OpenAPI generation. A generic third-party solution may solve 80 percent of the problem but require adapters, runtime reflection, conventions, or generic extension points that introduce more machinery than Kora wants. At that point, a framework-native implementation can reduce the number of layers:
Generic external tool
↓
adapter to Kora
↓
adapter configuration
↓
framework integration
↓
application
versus:
The second design can be simpler even though Kora owns more code. That is specialization, not automatically NIH.
Compile-Time Generation Changes the Trade-Off¶
Kora’s compile-time architecture is one of the strongest reasons it sometimes needs framework-native implementations. A generic runtime library may be designed around reflection or dynamic proxies. That can be completely reasonable for its own goals. Kora, however, explicitly wants to move structural framework work into the compiler, generate readable source, and minimize runtime interpretation. If an external library’s extension model fundamentally depends on runtime mechanisms Kora is trying to avoid, wrapping the library may produce an awkward hybrid:
In that situation, implementing a Kora-native generator can align the entire path with one model. The question is whether the benefits justify the maintenance cost.
Type Safety Can Justify Local Ownership¶
Framework-native code generation can also strengthen type guarantees. A generic integration must support many usage styles, frameworks, languages, runtime environments, and extension patterns. That breadth often requires generic metadata and late binding. A Kora-specific component can assume:
Kora graph semantics
Kora HTTP contracts
Kora config model
Kora mapping conventions
Kora telemetry interfaces
because those are known in advance. This narrower target allows more validation to happen before runtime. That is one of the legitimate reasons specialization can outperform generic reuse.
Predictable Behavior Can Matter More Than Feature Breadth¶
A generic library is often designed to be maximally configurable. That can be a strength, but it can also increase behavioral variation. If Kora wants one recommended solution and deterministic integration, a smaller specialized implementation may be easier to reason about. For infrastructure code, predictability has real value. Teams need to know what runs, what is generated, how lifecycle works, how telemetry is attached, and where configuration comes from. A smaller component that fits exactly into that model may provide more value than a generic library with a much larger option surface.
Performance Can Legitimately Change Build-vs-Buy Decisions¶
Performance is another valid reason to own an implementation, but it should be treated carefully. “We wrote it ourselves because it is faster” is not automatically credible. The difference needs to come from identifiable architectural properties. In Kora’s case, those properties may include compile-time code generation, direct method calls, lower reflection use, less dynamic proxy machinery, fewer allocation-heavy adapters, and specialized integration with the application graph. If the external library already provides equivalent performance with a clean integration model, reusing it is preferable. If the adapter chain would add enough runtime machinery to negate Kora’s design goals, a specialized implementation can be rational. Performance is a reason only when it can be demonstrated and maintained.
Unified Configuration Can Be a Real Benefit¶
Every external library comes with its own configuration model. Large applications can become difficult to operate when each integration invents a completely different configuration path, parsing model, lifecycle, telemetry toggle, and naming convention. Kora’s framework-native integrations can use typed configuration and consistent module conventions. That gives operators a more predictable application. Again, this does not require replacing the native library. It means owning the integration around it where consistency matters. The useful boundary is:
This is a much more disciplined goal than “wrap everything.”
Unified Telemetry Is Another Legitimate Ownership Point¶
The same applies to observability. A framework has a unique opportunity to provide consistent telemetry because it can see multiple subsystems at once. An external HTTP client may expose its own metrics hooks. A database library may expose another. Kafka has another. gRPC has another.
Kora can adapt these to a consistent telemetry model so that applications get coherent metrics, traces, and logs. This is framework-level value because cross-module consistency is something the individual libraries cannot provide on their own. Owning an adapter or small specialized integration for this purpose can be justified.
“One Problem — One Recommended Solution” Is Not a Ban on Alternatives¶
Kora’s philosophy favors one recommended solution per problem. This can easily be misunderstood as closed-world thinking. The stronger interpretation is:
not:
Those are very different positions. Kora’s explicit module and component model allows replacement and customization. Applications can provide their own components, add modules, integrate external libraries, and choose lower-level APIs where appropriate. A strong default is therefore not the same thing as a closed ecosystem.
Strong Defaults Reduce Decision Cost¶
The reason to provide one recommended solution is not ideological purity. It is to reduce decision overhead and compatibility matrices. If the framework officially supports five equivalent ways to implement the same concern, maintainers must document and test combinations among them. Users must choose. Teams must establish local conventions. AI tools and newcomers must determine which style is current. A strong default narrows the path:
while still allowing:
This is focused engineering.
Framework Scope Is Not a Defect¶
Another accusation often paired with NIH is that a framework implements only what its maintainers needed internally. The implication is that the scope is therefore illegitimate. That argument is too simplistic. Every framework has scope. Even the largest frameworks do not support every possible interpretation of every standard, every transport, every cloud service, every database, and every edge case. The question is whether the scope is explicit, useful, and honestly documented.
A framework that tries to support every theoretical scenario can accumulate a huge API surface, compatibility burden, test matrix, and long-term maintenance cost. Complete breadth is not free. A focused framework can rationally choose to support the common production path very well.
Narrow Scope Can Improve Quality¶
Consider the maintenance cost of one additional feature. It is not merely the implementation. It creates obligations for:
Multiply that by hundreds of optional behaviors and the maintenance surface can become enormous. A framework with a smaller scope can invest more deeply in the paths it does support. This is the architectural meaning behind Kora’s stated refusal to pursue breadth for its own sake.
But Scope Must Be Documented Honestly¶
Focused scope becomes unhealthy when maintainers dismiss valid use cases simply because the framework does not support them. There is an important line between:
“This is outside the current supported scope.”
and:
“Nobody needs this.”
The first is honest product scope. The second can become defensive engineering. If Kora claims support for a standard such as OpenAPI, then standards-compliant scenarios it does not support should be treated as feature gaps. They may be low-priority gaps. They may be intentionally deferred. They may be expensive to implement. But they remain gaps relative to the standard. That honesty is essential to making focused engineering credible.
OpenAPI Is an Excellent Case Study¶
OpenAPI generation illustrates the difference between generic reuse and specialization particularly well. A generic OpenAPI generator needs to support a very broad universe:
many languages
many HTTP frameworks
many serialization libraries
many runtime models
many server styles
many client styles
many configuration options
That breadth necessarily creates generic machinery. A Kora-specific generator can know much more about the target before generation begins. It knows:
the Kora HTTP client/server model
Kora mapping conventions
Kora configuration
Kora error model
Kora validation
Kora telemetry integration
the expected Java/Kotlin style
That allows the generator to produce code that is more idiomatic for the framework.
Specialization Can Produce Better Generated Contracts¶
A specialized generator can generate types and APIs aligned with the target architecture instead of relying on a lowest-common-denominator model. For example, it can make stronger assumptions about how server delegates are structured, how client configuration is supplied, how responses map to application types, and how generated handlers enter the Kora graph. This is valuable because code generation is most useful when the generated code feels native to the target environment. Generic breadth and target-specific quality are often in tension.
Generic Generators Pay for Options Kora Does Not Need¶
A generic generator might need switches for dozens of frameworks and runtime strategies. A Kora-specific generator can eliminate entire branches because the target is known. That can reduce:
The cost is narrower scope. This is exactly what specialization means.
Narrow Scope Must Not Pretend to Be Full Specification Coverage¶
The price of specialization is that unsupported corners may exist. OpenAPI itself has a large specification surface: complex schemas, polymorphism, discriminators, parameter serialization variants, security combinations, multipart forms, callbacks, links, unusual response structures, and vendor extensions. A framework-specific generator may not implement every possible combination. That is acceptable if the support boundary is clear. The healthy position is:
support the common production-relevant path very well
document unsupported standard-compliant cases
treat missing cases as normal feature gaps
The unhealthy position is:
Focused engineering requires discipline on both sides.
Kora’s OpenAPI Strategy Is Not Pure Reinvention¶
There is another nuance. Kora’s OpenAPI integration does not necessarily mean replacing the entire OpenAPI ecosystem. It can build on OpenAPI Generator infrastructure while specializing the generated Kora target. This is actually a strong example of the broader philosophy:
That is not NIH. It is composition. The framework does not need to reimplement parsing, normalization, schema handling, or every generic OpenAPI concern from scratch if mature tooling already exists. It can own the Kora-specific generation layer.
The Right Boundary Is Often “Generic Core + Specialized Edge”¶
This pattern appears repeatedly in good framework architecture. For example:
Kafka
↓
Kora lifecycle / telemetry / DI integration
gRPC
↓
Kora lifecycle / telemetry / DI integration
OpenTelemetry
↓
Kora module instrumentation
OpenAPI tooling
↓
Kora-specific generated client/server model
The mature external technology remains the core. Kora owns the edge where framework context is valuable. This is a disciplined reuse strategy.
Framework-Native Does Not Mean Framework-Exclusive¶
Another important distinction is between a framework-native default and mandatory framework ownership. Kora can provide its own repository generator without forbidding jOOQ or another data-access library. It can provide declarative HTTP clients without making it impossible to use a native HTTP client. It can provide built-in caching abstractions without preventing direct use of Caffeine. It can provide scheduling modules while allowing custom schedulers where necessary. The architecture should allow the application to choose an alternative when the built-in path is not a good fit. That is exactly what open extension points are for.
A Strong Default Is Not a Closed Ecosystem¶
This point deserves explicit emphasis:
A strong default is not the same thing as a closed ecosystem.
A closed ecosystem says:
An open application model says:
use the framework default
when it solves the common case
or
replace it with a custom/external implementation
through the same application model
Kora’s module and DI architecture is designed to support the second approach.
“One Recommended Solution” Is About Support Depth¶
The phrase “one problem — one recommended solution” should therefore be read as a maintenance policy. Kora can test, document, benchmark, optimize, and support one path deeply. That path becomes the default experience. If a specialized application needs something else, the framework does not need to pretend the alternative is equally first-class. It only needs to provide clean extension points and avoid trapping the application. This can produce a much healthier support model than claiming ten interchangeable solutions are equally recommended.
Open Source Changes the Lock-In Equation¶
Kora is open source. That does not eliminate lock-in, but it changes its shape. The source is inspectable. Generated code is inspectable. Framework internals can be studied. Extension points are available. Organizations can create modules, generators, adapters, or replacement components when needed. This is materially different from depending on an opaque proprietary runtime where the only supported behavior is whatever the vendor exposes. Open source does not make migration free, but it reduces informational asymmetry.
Generated Code Reduces Black-Box Dependence¶
Kora’s generated source is particularly relevant to the lock-in discussion. A framework-native generator does not necessarily hide the application behind an opaque abstraction. If the generated implementation is readable, the developer can see how the framework realizes the declaration. This makes framework ownership less risky because the implementation path is inspectable. The relationship becomes:
That is a much more transparent form of framework specialization.
Replaceability Matters More Than Purity¶
A useful way to evaluate Kora’s components is to ask:
If the answer is yes, then a strong built-in default creates much less strategic risk. For example, an organization may begin with the Kora-native solution because it is simple and well integrated. Years later, requirements may change. If the application graph allows another component or external library to be substituted, the initial decision has not become permanent. This is architectural optionality.
Kora’s Module System Is the Escape Hatch¶
The module model is central to that optionality. An external library can be made a first-class part of the application through:
The framework does not require every dependency to originate from Kora core. That is why Kora can afford to keep its official scope narrower. Extensibility is what makes focus viable.
Custom Modules Preserve Native APIs¶
A particularly healthy integration often exposes the native library directly. Suppose an application needs an SDK for a storage service. A module can create and configure the SDK client, manage its lifecycle, and expose it to application code. The business code still uses the SDK’s own API. This reduces semantic gap and makes vendor documentation directly applicable. The framework adds composition rather than replacing the vendor model.
External Tools Can Still Be Better Choices¶
Focused engineering also requires admitting when Kora’s built-in solution is not the best one for a particular application. A complex SQL-heavy service may prefer jOOQ. A specialized workflow may need a dedicated workflow engine. A sophisticated batch system may need a mature batch framework. An unusual OpenAPI workflow may need a different generator. A framework-native default should not become an ideological constraint. The correct architecture is the one that minimizes total complexity for the real workload.
Kora Should Not Win Every Build-vs-Buy Decision¶
A framework that always decides “build internally” is probably suffering from NIH. A framework that always decides “reuse externally” may fail to create a coherent product. Healthy engineering means making the decision separately for each capability. The framework should own only the small set of pieces where ownership creates a material advantage. That is the philosophy implied by Kora’s current scope.
The Ownership Test¶
A practical decision framework for Kora components might ask:
| Question | Why It Matters |
|---|---|
| Does framework context enable compile-time validation? | Specialized ownership may improve correctness |
| Can generated code remove runtime reflection or proxies? | Specialized ownership may reduce runtime machinery |
| Does the framework need end-to-end telemetry consistency? | A native adapter may add cross-module value |
| Is the external solution already a clean fit? | Prefer reuse |
| Would an adapter create more concepts than a native implementation? | Specialization may simplify |
| Does the built-in implementation create meaningful performance gains? | Ownership may be justified |
| Can users replace the component cleanly? | Reduces lock-in risk |
| Is the supported scope documented honestly? | Prevents focused scope from becoming dogma |
This is a more useful test than asking whether a component was written “in-house.”
“Own What You Can Own Well” Is a Maintenance Principle¶
There is another side to the title. Kora does not merely need reasons to build components; it needs the capacity to maintain them well. Owning a component means accepting long-term responsibility for:
If the project cannot maintain that responsibility, reuse is better. This is why focus matters. A framework with limited maintainer attention should not build hundreds of shallow abstractions simply to match another framework’s catalog. It should concentrate effort where it has a strong design advantage.
Breadth Can Become Maintenance Debt¶
Every new subsystem expands the test matrix. Suppose a framework supports multiple DI styles, multiple repository systems, several serialization models, multiple HTTP paradigms, and several concurrency models. Combinations multiply rapidly. Maintainers must test not only each feature but interactions among them. A smaller framework can invest in deeper confidence across fewer combinations. That is not automatically better, but it is a legitimate quality strategy.
API Surface Has Compound Cost¶
The maintenance cost of an API continues after release. Once users depend on it, the framework must consider compatibility. Deprecated APIs remain for years. Documentation must explain old and new paths. Migration tooling may be required. Every new public concept becomes part of the framework’s future. Focused engineering therefore treats API surface as a liability that must justify itself.
Internal Scenarios Are a Useful Starting Point, Not a Complete Standard¶
Many successful frameworks begin by solving real problems inside one organization. That can be a strength because the framework is shaped by production feedback rather than hypothetical feature lists. However, once the framework becomes public, maintainers need to distinguish between:
and:
A public framework cannot use internal usage as proof that unsupported external scenarios are irrelevant. Real-world internal focus should guide prioritization, not define universal truth.
Production Relevance Is a Better Prioritization Signal Than Feature Count¶
A focused framework can rationally prioritize features that repeatedly appear in production:
over rare or highly specialized cases. This is especially reasonable when the extension model lets advanced users solve the edge case themselves. The result can be a smaller framework that covers most production services exceptionally well. That is a viable product strategy.
Edge Cases Still Matter When Standards Are Claimed¶
The distinction becomes stricter when a module claims compatibility with a standard. If Kora says it supports OpenAPI, users reasonably expect standards-compliant contracts to work within a documented support boundary. When they do not, the missing scenario should be tracked like any other feature gap. The framework can still say:
but it should not redefine the standard around its own internal usage. This is the honest boundary between specialization and insularity.
Specialization Works Best When the Target Is Explicit¶
A Kora-specific implementation is easiest to justify when its target is narrow and clear. For example:
Generate code for Kora’s HTTP model
Integrate with Kora’s graph
Use Kora mappings
Use Kora telemetry
This is a concrete specialization target. The implementation can be tested against that target. A vague “our version is better” claim is much weaker. Focused engineering needs measurable goals.
Generic Tools Optimize for Breadth¶
Generic tools have a different mission. OpenAPI Generator, for example, needs to support a huge number of languages, libraries, styles, and options. That breadth is a remarkable ecosystem asset. But genericity creates constraints. Templates need to accommodate many targets. Shared abstractions must avoid assumptions that are valid only for one framework. Configuration options accumulate because different users need different output. A specialized Kora target can intentionally trade breadth for idiomatic integration. Neither strategy is inherently better. They solve different optimization problems.
Specialization Can Reduce Generic Machinery¶
When the target architecture is known, the generator does not need to preserve abstractions for frameworks that will never be used. That can simplify:
type mapping
error model
client configuration
server delegate design
validation integration
DI wiring
The generated output can look like native Kora code rather than code translated through a generic framework-neutral layer. This improves readability and reduces semantic distance.
Specialization Can Also Increase Maintenance Responsibility¶
The trade-off cuts both ways. Once Kora owns a generator target, it must keep pace with:
OpenAPI specification changes
OpenAPI Generator changes
Java/Kotlin changes
Kora HTTP changes
mapping changes
validation changes
This is real maintenance cost. A specialized implementation is justified only if Kora can continue owning that responsibility. Focused engineering therefore requires discipline not only in what is built, but in what is not built.
The Framework Should Prefer Ecosystem Leverage¶
Kora gets maximum leverage when it reuses mature external technologies and adds only the integration needed to make them fit the application model. A conceptual stack is:
This preserves external innovation. When Kafka improves, Kora benefits. When PostgreSQL improves, Kora benefits. When OpenTelemetry evolves, Kora can align with the standard rather than maintain a parallel universe. That is the opposite of ecosystem isolation.
The Framework Should Build When the Adapter Is the Complexity¶
There are cases where wrapping an external tool introduces as much or more complexity than a native solution. Suppose an external DI container requires runtime scanning and proxies, but Kora’s architecture depends on compile-time graph knowledge. An adapter would need to bridge two incompatible component models. At that point, “reuse” may mean maintaining:
A native DI engine may actually be the simpler system. The same logic can apply to other components. Reuse is not automatically simpler.
Layer Count Matters¶
A useful architectural metric is not “how many external dependencies do we use?” but “how many semantic layers exist on the critical path?” Compare:
with:
The second system can be easier to debug and operate even though Kora owns more implementation. NIH analysis must consider total system complexity, not the origin of source code.
Dependency Count Is Not Ecosystem Health¶
A framework that depends on more external projects is not necessarily healthier. A framework that depends on fewer is not necessarily NIH. The important questions are:
Are dependencies mature?
Are responsibilities clear?
Is duplication justified?
Can the system be maintained?
Architecture should be evaluated by boundaries, not dependency count.
Framework-Native Runtime Pieces Can Be Appropriate¶
Some low-level runtime pieces may also justify framework ownership when Kora needs very specific performance or lifecycle behavior. Again, the burden of proof is higher. Runtime infrastructure is security- and correctness-sensitive. Reusing mature libraries is usually preferable. But there are situations where a small specialized component can eliminate multiple adapter layers or align tightly with Kora’s runtime model. The decision must be evidence-driven.
Performance Should Never Become NIH Theater¶
There is a common failure mode where teams justify reinventing mature software by claiming they can make it faster. Without benchmarks, operational evidence, and long-term maintenance commitment, this is weak reasoning. Kora’s performance philosophy should therefore be applied selectively. Build a specialized component only when the architectural advantage is real enough to measure or when integration quality clearly improves. Performance is a legitimate optimization target, not a blank check.
Simplicity Is Also a Legitimate Goal¶
Not every custom implementation needs to win a benchmark. Sometimes a small framework-native component is justified because it removes a much larger generic abstraction surface. If a 2,000-line specialized adapter can replace a dependency that brings a complex runtime model and dozens of configuration concepts, the net system may become simpler. Simplicity is harder to measure than throughput, but it has real maintenance value. The relevant question is total cognitive and operational complexity.
Unified Behavior Can Be Worth More Than Generic Flexibility¶
Enterprise teams value consistency. If retries, timeouts, telemetry, configuration, and lifecycle behave similarly across Kora modules, developers can learn one model and apply it everywhere. A generic external tool may provide more options but require a distinct programming model. Kora can rationally choose the specialized implementation if consistency produces significant organizational value. Again, this should be evaluated against actual requirements rather than ideology.
The Best Default Should Cover the Common Case Deeply¶
A strong framework default should optimize the path most services actually use. That means:
good documentation
good diagnostics
good telemetry
good testing
predictable behavior
reasonable performance
The default does not need to solve every imaginable variation. It needs to be excellent at the path the framework recommends. This is a much more sustainable goal than universal breadth.
Escape Hatches Protect Against Wrong Assumptions¶
No framework maintainer can predict every application. This is why replaceability matters so much. A strong default is safe only when the framework admits:
and provides a clean path to substitute another implementation. Kora’s explicit application graph and module architecture are valuable precisely because they can provide that escape hatch.
External Implementations Should Fit the Same Application Model¶
The best extension system does not require a parallel plugin universe. A custom component should be able to enter the graph using the same concepts as built-in modules:
This reduces the distinction between “official” and “custom” integration at the architectural level. The official implementation may have more documentation and optimization, but the application model remains coherent.
This Is How Kora Avoids a Closed Ecosystem¶
The architecture is not:
It is closer to:
That is the crucial difference between an opinionated framework and a closed framework. Kora can be strongly opinionated without requiring every organization to accept every implementation forever.
Open Source Makes Specialization Auditable¶
When a framework owns a specialized component, users should be able to inspect why. Open source lets engineers answer:
What does this generator actually emit?
What runtime path does this module use?
Where is telemetry attached?
What are the constraints?
Kora’s generated source adds another layer of transparency because users can inspect not only the framework implementation but the application-specific output. This is valuable accountability.
Generated Code Makes Specialization Less Magical¶
A specialized framework implementation is more concerning when it becomes an opaque black box. Kora’s compile-time architecture often goes the other way. The specialized component produces ordinary Java/Kotlin. That means the result can be:
using standard tools. The framework owns the generation logic, but the runtime path becomes more explicit. This is a strong argument for specialization where code generation provides value.
Lock-In Is More About Semantics Than Source Location¶
A library can be external and still create deep lock-in if it imposes a proprietary programming model throughout the business code. A framework component can be internal and create relatively little lock-in if it generates thin adapters around standard technologies. Therefore:
external dependency
≠ automatically portable
framework-native implementation
≠ automatically locked in
The real question is how much application code depends on framework-specific semantics. Kora’s thin abstractions try to keep that surface limited.
Native Technology Knowledge Remains Transferable¶
This matters operationally. A Kora engineer debugging PostgreSQL still learns PostgreSQL. A Kora engineer debugging Kafka still learns Kafka. A Kora engineer inspecting traces still learns OpenTelemetry. The framework-specific implementation does not attempt to make those technologies disappear. That preserves transferable knowledge even when the integration itself is Kora-native.
Framework-Specific Components Should Be Small in Number¶
Selective ownership only remains credible if it stays selective. If Kora begins building replacements for every database driver, every cloud SDK, every broker client, every observability backend, and every testing tool, the architecture would drift toward the NIH behavior it currently avoids. The framework’s own philosophy acts as a constraint: do not pursue breadth for its own sake. That principle should remain visible in future design decisions.
The Absence of a Module Can Be Healthy Restraint¶
When a framework does not have a dedicated integration for some niche technology, that is not always evidence of immaturity. It may mean:
the native Java client is already good
integration is trivial
maintainers do not want to own another API
usage is too niche to justify core support
Of course, sometimes it simply means the feature is missing. The point is that absence must be interpreted, not automatically scored negatively.
Build Versus Buy Should Be Revisited Over Time¶
A decision that was correct five years ago can become wrong later. An external ecosystem solution may mature. A Kora-native implementation may become expensive to maintain. A standard may emerge. Conversely, an external library may stagnate while Kora’s needs become more specialized. Healthy architecture revisits ownership boundaries. NIH becomes dangerous when ownership turns into identity and the team refuses to reconsider.
Replacing Internal Components Should Be Possible¶
If a better external solution emerges, Kora should be able to integrate it without rewriting the framework’s whole architecture. This is another reason to keep boundaries clean. Framework-native components should implement explicit contracts. Modules should isolate construction. Application code should depend on useful interfaces rather than internal machinery where possible. Replaceability is an architectural discipline.
Maintainers Need the Ability to Say “No”¶
Focused engineering depends heavily on restraint. Users will ask for:
another database
another serialization format
another scheduler
another cloud SDK
another framework adapter
another compatibility mode
Some should be added. Some should remain external integrations. Some should be rejected because they would permanently expand the core without enough benefit. A healthy framework does not measure success by the number of modules it owns.
Scope Discipline Protects Quality¶
Maintainers have finite attention. Every hour spent keeping an obscure integration compatible is an hour not spent improving:
A focused project can preserve quality by refusing to dilute effort across too many shallow integrations. This is particularly important for a framework with a smaller core team than the largest industry platforms.
“Built Only for Internal Scenarios” Is Too Crude a Criticism¶
The criticism contains a legitimate concern: a public framework must work beyond the organization that created it. But the conclusion should not be that every internal constraint must be removed. All frameworks emerge from some set of requirements. The real questions are:
Are the supported scenarios useful outside the original organization?
Are limitations documented?
Can users extend the system?
Are missing standard features treated honestly?
If the answers are yes, origin is less important than product quality.
Real Production Scope Can Be an Advantage¶
A framework built from real production requirements may avoid speculative complexity. It can prioritize concerns that actually matter:
startup
resource efficiency
observability
graceful shutdown
data access
resilience
predictable lifecycle
This can be healthier than implementing features merely because they appear on competitors’ checklists. Production pressure can sharpen scope.
But Internal Experience Must Not Become Dogma¶
The danger appears when maintainers assume:
That reasoning is not acceptable for a public framework. A production-focused project still needs to listen to external use cases. Focused scope should be a prioritization strategy, not a way to invalidate users. This is especially important around standards.
OpenAPI Requires Explicit Compatibility Boundaries¶
OpenAPI is a public standard, so Kora’s generator should make its supported subset clear. A user who provides a valid OpenAPI document should be able to determine whether the generator supports the relevant features. Unsupported cases should be documented where possible and treated as ordinary compatibility gaps. This is both technically honest and strategically useful. It lets teams decide whether Kora’s specialized generator fits before committing to it.
Specialization Is Stronger When It Is Honest About Limits¶
A narrow implementation does not need to pretend to be universal. In fact, its credibility improves when it says:
We optimize these scenarios.
We support these specification features.
These cases are not yet supported.
Use an alternative when your needs fall outside the scope.
That is a mature engineering posture. Focused products become dangerous only when narrowness is hidden.
Generic Versus Specialized Is an Optimization Choice¶
A generic solution optimizes:
A specialized solution optimizes:
Both approaches are useful. Kora should specialize where the second set of properties matters enough to justify narrower scope. That is the rational boundary.
The OpenAPI Generator Trade-Off in One View¶
Generic generator
many languages
many frameworks
many modes
many options
↓
broad compatibility
↓
more generic machinery
versus:
Kora-specific target
known framework
known HTTP model
known DI model
known mappings
known error model
↓
idiomatic generated code
↓
narrower scope
Calling the second approach NIH simply because it is specialized misses the trade-off.
Kora Can Reuse and Specialize Simultaneously¶
The most interesting point is that these choices are not mutually exclusive. Kora can reuse mature generic infrastructure while specializing the pieces that need framework knowledge. This produces a layered strategy:
The value of the integration should be judged by what it removes or guarantees. That is much more precise than categorizing all custom code as reinvention.
AI Development Makes Focused Integration More Viable¶
There is also a modern change in the cost equation. Historically, custom integration code could be expensive because engineers had to write repetitive setup, documentation, tests, and examples manually. AI agents can now help with:
This does not eliminate maintenance or review, but it reduces the marginal cost of integrating a mature native library without waiting for an official framework module. That makes Kora’s “extend through the normal application model” strategy increasingly practical.
AI Also Benefits From Transparent Specialization¶
An AI agent can inspect generated Kora code and understand the exact behavior of a specialized implementation. This is important because framework-native components do not become opaque simply because they are custom. The agent can read:
and reconstruct the path. Transparency reduces the risk traditionally associated with proprietary framework machinery.
Compile-Time Contracts Give Agents Immediate Feedback¶
If an agent integrates an external SDK through a Kora module incorrectly, the application graph can fail during compilation. If a generated mapper is invalid, the compiler can reject it. If a framework-native AOP aspect cannot be applied, the build can fail. This means both built-in and custom integrations participate in the same feedback model. That is another reason the extension system matters more than the size of the official catalog.
Focused Engineering Helps AI by Reducing Branches¶
“One recommended solution” also reduces the number of implementation paths an AI agent must consider. If Kora has a canonical repository model, the agent is less likely to mix incompatible styles. If the framework does not wrap every external technology, the agent can use the native library documentation directly. A smaller conceptual surface can therefore improve automated development. Again, strong defaults are useful because they narrow ambiguity, not because alternatives are forbidden.
The Framework Should Avoid Inventing Vocabulary Without Benefit¶
Every proprietary abstraction introduces terminology. If Kora can use:
there is little value in renaming those concepts solely to make them “Kora concepts.” A framework-native abstraction should earn its vocabulary by providing something substantial. This keeps the learning curve closer to ordinary JVM backend engineering.
Reuse Preserves External Documentation¶
One of the hidden advantages of thin integration is documentation reuse. When Kora uses a native vendor SDK, developers can follow the vendor’s documentation. When it uses Kafka directly, Kafka documentation applies. When it uses JDBC, decades of JDBC knowledge apply. This is ecosystem leverage. A large proprietary abstraction can inadvertently discard that advantage by forcing developers through a translation layer.
Reuse Preserves Tooling Too¶
The same is true for tools. PostgreSQL tools still work. Kafka tools still work. OpenTelemetry tooling still works. gRPC tooling still works. Kora does not need to recreate operational tooling for technologies whose ecosystems already provide better tools. This is another reason building everything internally would be irrational.
Framework-Native Code Should Focus on Cross-Cutting Leverage¶
The strongest candidates for framework ownership are components where Kora can use knowledge from multiple parts of the application. Examples include:
DI graph
lifecycle
telemetry propagation
compile-time AOP
generated repositories
generated HTTP adapters
These features benefit from being aware of Kora’s application model. A random vendor SDK usually does not. This is a useful ownership heuristic.
End-to-End Guarantees Are Hard to Add Through Adapters¶
Suppose Kora wants to guarantee that:
dependency graph errors fail at compile time
AOP code is generated rather than proxied dynamically
telemetry is attached consistently
configuration is strongly typed
If a critical subsystem hides these details behind a generic runtime abstraction, Kora may be unable to make that guarantee end to end. This is when framework-native ownership becomes especially compelling. The integration is not merely convenience; it is part of the framework contract.
End-to-End Ownership Should Be Rare¶
However, this argument should not become self-justifying. Almost any framework could claim it needs end-to-end control over everything. Kora’s philosophy remains credible only if it limits that claim to the components where the benefit is substantial. That means defaulting to reuse and requiring justification for ownership. The burden of proof should be on the custom implementation.
The Burden of Proof Is Healthy¶
Before building a Kora-native component, maintainers should be able to answer:
What external solutions exist?
Why do they not fit?
What property do we gain by owning this?
What maintenance cost are we accepting?
Can users replace it?
How will we test it?
What scope do we promise?
If those questions have weak answers, reuse is probably better. This is how focused engineering avoids turning into NIH.
“We Can Write It Better” Is Not Enough¶
Engineers naturally enjoy building systems. That makes framework teams particularly vulnerable to unnecessary reinvention. A mature decision process must resist the instinct to implement something merely because it is technically interesting. The custom solution needs a product reason. For Kora, the strongest reasons are aligned with its core identity:
compile-time guarantees
performance
transparency
type safety
coherent configuration
coherent telemetry
Outside those areas, reuse should usually win.
Ownership Should Produce a Simpler Total System¶
This is perhaps the most important test. A Kora-native implementation is justified when:
is simpler than:
The comparison must include all layers. A single extra dependency can introduce a surprisingly large conceptual and operational surface. Conversely, a custom implementation can create years of maintenance debt. Only the total system matters.
A Smaller Codebase Is Not Always a Simpler System¶
This is why line-count arguments are weak. Using a giant external library may reduce Kora’s own source code while increasing:
Writing a small specialized component may increase repository size while reducing total architecture. Simplicity must be measured at the system boundary, not the repository boundary.
External Maturity Is Still a Major Asset¶
None of this should understate the value of mature libraries. External projects can provide:
years of production hardening
security review
specialized maintainers
large user communities
rare edge-case fixes
Reimplementing those benefits is expensive. Kora should reuse mature infrastructure whenever its architectural goals can be preserved. That is why JDBC, Kafka, gRPC, OpenTelemetry, and other established technologies remain central.
Specialized Components Need Strong Tests¶
When Kora chooses to own something, the testing obligation increases. A framework-native generator or runtime piece should be tested across:
common scenarios
failure cases
version compatibility
generated-code compilation
performance-sensitive paths
Specialization is only valuable if quality is high. A narrow implementation with weak tests is worse than a mature external library.
Specialized Components Need Clear Documentation¶
The same is true for docs. Narrow scope must be discoverable. Users should understand:
what the component supports
what it does not support
how to replace it
how to inspect generated behavior
This is particularly important for standards-related modules such as OpenAPI. Focused engineering depends on clear contracts.
Specialized Components Need Upgrade Discipline¶
Owning an implementation also means owning migration. If a Kora-native API changes, the framework should explain the new model. If an underlying standard changes, the integration needs a compatibility strategy. If generated code changes materially, users need to understand the implications. This is another reason to keep the number of framework-owned components controlled.
The Framework Should Not Compete With Every Library¶
Kora does not become stronger merely by having:
That would mostly duplicate ecosystems that already work. The framework is stronger when it knows where not to compete. Focus is as much about omission as implementation.
The Best Framework Boundary Is Uneven¶
A good architecture does not draw the framework boundary at one uniform abstraction level. Some areas deserve deep framework ownership. Others deserve a thin adapter. Others need no adapter at all. This uneven boundary is a sign of engineering judgment. It reflects the actual value of integration rather than a desire for conceptual symmetry.
Kora’s Boundary Is Intentionally Asymmetric¶
Kora owns DI deeply. It owns compile-time generation deeply. It owns the application graph and lifecycle. It integrates external technologies more lightly where their own APIs are already strong. That asymmetry is logical. The framework does not need to treat every subsystem identically.
Focused Engineering Is Compatible With a Rich Ecosystem¶
A framework can remain focused while still supporting many technologies through external modules. The ecosystem does not have to mean everything belongs in core. Community integrations, organization-specific modules, and vendor adapters can all participate in the same application model. This separates:
from:
That is a healthy distinction.
Core Scope and Ecosystem Scope Should Not Be Confused¶
Kora core can remain small while applications use a large ecosystem. That is exactly what happens when the framework integrates ordinary JVM libraries cleanly. The absence of an official core module does not mean the technology is unavailable. The practical question is the cost of integration. If the cost is low, a focused core can support a broad ecosystem without owning it.
This Reduces Core Governance Pressure¶
A framework that accepts every integration into core inherits governance responsibility for all of them. Keeping many integrations external can let specialized maintainers own the technologies they understand best. Kora core can focus on the application model and official essentials. This can improve maintainability.
Official Modules Should Represent Strong Commitments¶
When Kora does bring something into the official framework, users should interpret that as a stronger commitment:
this is part of the recommended model
this should integrate coherently
this should be documented
this should be maintained
That makes the official catalog more meaningful. Breadth becomes less important than quality of commitment.
The Framework Should Be Able to Delete Bad Ideas¶
Focused scope also improves the ability to evolve. A huge public surface makes architectural mistakes difficult to remove. A smaller surface gives maintainers more freedom to improve the model. Kora 2’s willingness to simplify and consolidate its programming model reflects this priority. Evolution can still be painful for existing users, but long-term coherence benefits.
Compatibility Is a Cost, Not an Absolute Good¶
Frameworks should respect compatibility, but compatibility has a price. Preserving every historical path can leave newcomers with multiple generations of APIs. Focused engineering sometimes accepts a breaking migration in exchange for a cleaner current model. That is not always the right choice, but it is a legitimate one. Kora’s approach tends to favor current coherence over indefinite preservation of every old abstraction.
Specialization and Simplicity Reinforce Each Other¶
A Kora-specific generator can be simpler because it knows the target. A Kora-specific DI engine can be simpler because it knows the graph is static at build time. A Kora-specific AOP model can be simpler because it generates code rather than supporting arbitrary runtime proxy scenarios. These design choices narrow scope and reduce runtime machinery simultaneously. That is the strongest case for owning a component.
Specialization Is Weak When It Merely Renames an External API¶
The opposite is also true. If a Kora-specific wrapper does nothing except rename methods from a mature library, it adds semantic distance without meaningful value. Such abstractions should be viewed skeptically. A good framework integration should contribute:
Otherwise direct use of the library is usually preferable.
Adapter Layers Have a Maintenance Cost Too¶
Teams sometimes assume reuse is free. An adapter can become a permanent maintenance layer. If it must translate:
between Kora and another framework, it may create as much work as a specialized implementation. This is why “just use library X” is not always the simple answer. The integration cost must be counted.
Frameworks Should Minimize Translation Layers¶
A healthy Kora integration tries to avoid chains such as:
Every translation creates potential mismatch. If Kora can integrate directly with the mature native technology, the architecture is clearer. This aligns with its thin-abstraction philosophy.
The Same Principle Helps Debugging¶
When a production problem occurs, fewer layers make root cause analysis easier. A JDBC exception should look like a database problem. A Kafka rebalance should look like Kafka. A gRPC deadline should look like gRPC. Framework-native code should clarify these paths, not obscure them. Focused engineering is partly about preserving observability of the real system.
A Framework Can Be Opinionated Without Being Isolationist¶
This is the broader architectural lesson. Kora can say:
while simultaneously saying:
Opinionated defaults and ecosystem openness are compatible. Confusing them leads to unnecessary framework wars.
The Important Distinction Is Default Versus Constraint¶
A default says:
A constraint says:
Kora aims to provide strong defaults. Its extension model should keep them from becoming hard constraints. That distinction should remain a design invariant.
This Is Also a Better Model for Enterprise Platforms¶
Enterprise platform teams benefit from strong defaults because they want consistency. They also need exceptions because large organizations always contain unusual workloads. A Kora-based platform can provide:
and allow:
without abandoning the application model. This balances standardization and flexibility.
Custom Integrations Should Not Become Second-Class Architecture¶
If custom modules use the same DI, config, lifecycle, telemetry, and testing patterns as built-in modules, they remain first-class participants in the system. This is important. An extension model is weak if custom code lives outside observability, lifecycle, or testing conventions. Kora’s architecture is strongest when built-in and custom components share the same structural model.
Focused Scope Supports Better AI Guidance¶
A smaller official surface is also easier for AI tools to learn. Agents have fewer competing patterns to choose from. Generated code makes built-in components inspectable. External libraries remain recognizable because Kora does not hide them behind proprietary vocabulary. This improves both code generation and debugging. Focused engineering therefore has a modern tooling benefit in addition to maintainability.
AI Does Not Remove the Need for Maintainers¶
It may become easier to generate integrations, but ownership still requires judgment. Someone must decide:
Is the external library safe?
Is lifecycle correct?
Is telemetry meaningful?
Is the module API stable?
Is the feature worth supporting long term?
AI reduces implementation cost. It does not remove maintenance responsibility. This reinforces the value of deliberate scope.
Focused Engineering Is Ultimately About Responsibility¶
The title “build only what you can own well” is less about code and more about responsibility. To own a component well means being willing to:
That is expensive. A framework should accept that responsibility selectively. Kora’s best architectural decisions are the ones where ownership produces enough value to justify the commitment.
The Wrong Extreme Is “Everything External”¶
There is also a failure mode on the other side. A framework that refuses to own anything can become little more than dependency aggregation. Every subsystem has a different configuration model. Every integration has separate telemetry. Lifecycle is inconsistent. Errors appear in different phases. The developer experiences the complexity of the entire JVM ecosystem without a coherent application model. That is not automatically better than NIH. Framework value comes from selective integration.
The Right Goal Is Coherent Composition¶
Kora’s purpose is to make backend components behave like one application:
one graph
one lifecycle
one configuration philosophy
one telemetry model
one compile-time feedback model
That requires some framework-native infrastructure. The art is to achieve coherence without unnecessarily replacing mature technology. This is the balance Kora is trying to strike.
A Simple Decision Matrix¶
A practical build-or-reuse matrix can look like this:
| Situation | Preferred Direction |
|---|---|
| Mature external technology with clean Java API | Reuse directly |
| Mature technology but needs lifecycle/config/telemetry wiring | Thin Kora integration |
| Generic tool creates heavy adapter/runtime machinery | Consider Kora-native specialization |
| Compile-time guarantees require framework knowledge | Framework-native generator/component |
| Feature is niche and native client is already excellent | Keep outside core |
| Standard feature is missing from Kora implementation | Treat as a feature gap, not as unnecessary |
| Internal need is highly organization-specific | Custom module, not necessarily core |
| Built-in default no longer fits application | Replace through application model |
This captures the difference between focused ownership and NIH much better than a simple “custom code is bad” rule.
Kora’s Architecture Makes This Strategy Plausible¶
The reason the philosophy works is that Kora has a clear application model into which both official and external components can fit. The same graph can contain:
The framework does not require everything to originate from the same codebase. This architectural openness is what makes selective ownership credible.
Without Extensibility, Focus Would Become Restriction¶
If Kora offered only its official components and made alternatives difficult to integrate, a narrow scope would be a liability. Focused engineering depends on replaceability. The application model must be open enough that users can solve problems outside the core roadmap. This is why “Built to be extended” is not a secondary marketing point. It is structurally necessary to Kora’s philosophy.
Without Strong Defaults, Extensibility Would Become Fragmentation¶
The opposite is also true. If Kora provided only extension points and no strong defaults, every team would build its own stack. That would destroy consistency. The framework therefore needs both:
The combination is what makes the model work.
The Best Frameworks Know What Not to Own¶
This may be the most important strategic lesson. A framework is defined not only by what it implements, but by what it deliberately leaves to the ecosystem. Kora does not need to own Kafka because Kafka is already Kafka. It does not need to own OpenTelemetry because OpenTelemetry is already a standard. It does not need to replace every vendor SDK because vendor SDKs already exist. It should own the parts where Kora-specific knowledge creates a better system. That is focused engineering.
What Kora Should Continue to Resist¶
To preserve this philosophy, Kora should resist several temptations:
adding framework wrappers merely for naming consistency
absorbing niche integrations into core without maintainers
claiming unsupported standard features are irrelevant
creating DSLs where Java/Kotlin already express the task well
preserving weak legacy APIs forever for compatibility
Each of these would increase surface without necessarily increasing value. Focus requires continuous restraint.
What Kora Should Continue to Invest In¶
The high-leverage areas are clearer:
compiler diagnostics
generated-code quality
application graph
module extension points
telemetry consistency
testing
documentation
migration clarity
These are foundational capabilities that improve every integration, including custom ones. Investing here makes the whole ecosystem stronger without requiring Kora to own every technology.
The Difference Between Product and Collection¶
A framework should feel like a coherent product rather than a collection of libraries. Selective framework-native components create that coherence. But a coherent product does not need to internalize every dependency. The best architecture finds the smallest set of owned mechanisms capable of making the rest of the ecosystem feel integrated. That is a more sophisticated goal than either “build everything” or “wrap nothing.”
Kora’s Philosophy Is Almost the Opposite of NIH¶
A genuine NIH organization distrusts external technology by default. Kora’s architecture depends heavily on external technology by default. It assumes the ecosystem already contains excellent:
and tries to avoid replacing them. Where Kora builds its own pieces, the justification should be that those pieces are intrinsic to Kora’s value proposition. That is specialization layered on top of reuse.
Final Principle: Reuse the Technology, Own the Integration When Necessary¶
The most concise way to describe the model is:
That is the boundary Kora should continue to defend. It allows the framework to remain coherent without becoming a universe. It keeps the application close to the JVM ecosystem. It makes custom integrations practical. It gives maintainers a rational way to decide what belongs in core.
Conclusion¶
The accusation of NIH becomes useful only when it distinguishes unnecessary reinvention from justified specialization. Building something inside a framework is not automatically NIH. The relevant question is whether a mature external solution already fits the requirements and whether replacing it creates enough additional value to justify the maintenance burden.
Kora’s architecture is not based on rewriting the ecosystem. It is built on top of it. JDBC remains the database foundation. Kafka remains Kafka. gRPC remains gRPC. OpenTelemetry remains the observability standard. Mature JVM libraries, vendor SDKs, Gradle, JUnit, Testcontainers, and cloud-native infrastructure remain available directly.
Where Kora does own framework-native components, the strongest justification is that ownership lets it enforce properties that would be difficult to preserve through another abstraction layer: compile-time graph validation, generated source, type safety, predictable behavior, low runtime machinery, coherent configuration, and integrated telemetry. That leads to a better question than “why did you build this yourself?”:
What does the framework-specific implementation give us that another adapter layer over an external tool would not?
If the answer is weak, Kora should reuse the external solution. If the answer is strong and measurable, specialization can be the simpler architecture. OpenAPI generation illustrates the trade especially well. A generic generator must support many languages, frameworks, modes, and options. A Kora-specific target can know the target architecture in advance and generate more idiomatic clients, servers, mappings, validation, and error handling. The price is narrower scope. That is not automatically NIH; it is specialization. But specialization also creates an obligation to document its boundaries honestly. Standards-compliant scenarios that are not supported remain feature gaps and should be treated as such.
The same honesty applies to framework scope more broadly. Supporting the common production path extremely well can be a strength. Trying to implement every theoretical edge case can create an enormous API, compatibility burden, and test matrix. Yet “focused scope” must never become an excuse for dismissing legitimate user needs. A public framework must distinguish between “outside our supported scope” and “nobody needs this.”
Kora’s open architecture helps make that trade safer. The framework is open source. Generated code is visible. Components can be replaced. Custom modules can participate in the same DI, configuration, lifecycle, telemetry, and testing model. External libraries can be used when they fit better. That means the architecture is not:
It is closer to:
This is why two principles belong together:
A strong default is not the same thing as a closed ecosystem.
and:
“One problem — one recommended solution” does not mean “one solution you are forbidden to replace.”
Focused engineering is ultimately a statement about responsibility. Every framework-owned component creates a long-term obligation to test, document, secure, optimize, upgrade, and support it. Kora should therefore own only the components where ownership produces enough architectural value to justify that obligation. That leads to the final thesis:
NIH is building your own version of everything because you distrust the ecosystem. Kora’s philosophy is almost the opposite: reuse established technologies by default, but own the small number of components where framework-specific implementation produces materially better guarantees or developer experience.
That is not isolation. It is scope discipline. And for a framework whose core goals are compile-time certainty, transparency, performance, and a small coherent programming model, scope discipline is not a limitation. It is part of the architecture.