Sitemap
Helidon

The official project Helidon blog containing articles from Helidon developers and the developers community. All articles are approved by the Helidon team.

Helidon 27 Released

15 min readSep 21, 2026

--

Press enter or click to view image in full size

The Helidon team is pleased to announce Helidon 27, our first release under the Tip-and-Tail model used by OpenJDK.

This release changes how Helidon moves with Java. Teams that want the latest JDK and Helidon features can follow the Tip, while teams that need a longer-lived production baseline can remain on the Tail.

Helidon 27 is the Tip. Helidon 4.5 remains the LTS Tail.

TL;DR

  • Helidon 27 is the first Tip release and requires JDK 27.
  • Helidon 4.5 remains the LTS Tail.
  • Declarative API coverage is now complete with gRPC, Messaging, GraphQL, and OpenAPI. The APIs remain in Preview, with finalization planned for Helidon 29 LTS.
  • Helidon 27 introduces two major modules: Helidon Messaging and Helidon Data JDBC.
  • Choose Helidon 27 if you want to work with the latest Java and help shape new Helidon APIs.
  • Stay on Helidon 4.5 if you need the long-lived LTS baseline.

Innovation at the Tip. Stability at the Tail.

When we released Helidon 4.4, we announced that Helidon would adopt the Tip-and-Tail model of development. We also announced that future Helidon Tip releases would track the JDK version.

Helidon 27 puts that model into practice: Want to use Helidon 27? Use JDK 27. Easy!

Press enter or click to view image in full size
One release strategy. Two complementary paths.

Tip is for teams that want the latest JDK release and Helidon features on a faster cycle. New APIs arrive here first, and feedback from Tip users helps us prepare them for the next Tip and LTS releases.

Tail is for organizations with longer validation, migration, and production-support requirements. Helidon 4.5 is the current LTS Tail, so teams that need more time do not have to move simply because the Tip has advanced.

What does it mean for support you ask me? There 2 types of Tip releases:

  1. Non-LTS: supported for six months until the next Tip
  2. LTS: supported until one year after the following LTS

Let’s illustrate this with an example:

Press enter or click to view image in full size

Helidon 27 (non-LTS) continues to receive fixes until Helidon 28 (non-LTS) is released. Helidon 28 also receives fixes until Helidon 29 (LTS) is released.

When Helidon 29 is released, at that point in time, it becomes the Tip. However, since Helidon 29 is also an LTS release, it is supported and will continue to receive fixes until one year after the next LTS release (Helidon 33). LTS releases typically follow a 2-year cycle. Thus, a Helidon LTS release is supported for 3 years. When Helidon 30 is released (alongside JDK 30), Helidon 29 becomes a Tail. Support for Helidon 4.5 LTS ends 1 year after Helidon 29 LTS is released.

JDK 21 has been the baseline for the Helidon 4 release line since September 2023. Since Helidon 4.3, we have recommended running on JDK 25 because of the performance improvements it brought. However, retaining JDK 21 compatibility meant that Helidon itself could not use newer Java features throughout the framework.

Moving the baseline to JDK 27 changes that. Helidon can now use Java features that became generally available after JDK 21, including Scoped Values.

New JDK releases also tend to include runtime improvements and fixes. The benchmark discussed in the Helidon 4.3 release article showed approximately 70% higher throughput for the same application after moving from JDK 21 to JDK 25. As always, benchmark results depend on the application, workload, hardware, and test configuration, so we encourage you to validate them against your own workloads.

Performance uplift when upgrading from JDK 21 to JDK 25

Tip-and-Tail lets us do two things that were previously difficult to reconcile: move quickly with modern Java at the Tip while maintaining a stable LTS baseline at the Tail.

Scoped Values: Let Java Carry the Context

Scoped Values are a concrete example of what advancing Helidon’s JDK baseline enables.

A context should live exactly as long as the work that needs it. Starting with Helidon 27, the active Helidon context is carried using JDK ScopedValue rather than the previous ThreadLocal-based implementation.

Scoped Values bind data to a defined execution scope and automatically restore the previous binding when that scope ends. They are also designed to work efficiently with virtual threads.

For Helidon, this means less mutable context state to manage and less risk of context outliving the operation to which it belongs.

Applications receive these benefits without code changes. The public Helidon Context API remains unchanged.

Core and Extensions: Different Ecosystems, Different Clocks

The distinction between Helidon SE and Helidon MP has served us well, but Helidon now provides features that do not fit neatly under either programming model. Helidon 27 describes that structure more clearly, gives its parts clearer names, and lets them follow the projects on which they depend.

With Helidon 27, we move away from the Helidon SE name.

The shared foundation — including configuration, networking, security, observability, and common runtime services — is now called Helidon Core.

Press enter or click to view image in full size
Programming Models in Helidon

Helidon Core provides two built-in programming models:

  • Imperative which gives you plain Java and direct control, without needing dependency injection or annotations. What you code is what you get. This is the programming model previously known as Helidon SE.
  • Declarative which gives you dependency injection and annotations. Helidon generates the imperative code and wiring at build time. You get the convenience of a declarative model without hiding the implementation behind runtime reflection or bytecode manipulation.

As for Helidon MicroProfile, it remains our standards-based programming model for MicroProfile and supported Jakarta EE specifications. For now, it continues on the Helidon 4.5 LTS line. Future releases will follow a cadence aligned with MicroProfile and Jakarta rather than being tied directly to the Helidon Core release cycle.

Capabilities that build on Helidon Core but follow external ecosystems are called Helidon Extensions. Helidon MCP, the LangChain4j integration, and OCI integration are among the many extensions in this group.

I want to stress that this is not an architectural rewrite. The new names describe the architecture we already have and enable its parts to release when their own ecosystems require it.

Press enter or click to view image in full size
Different ecosystems. Different clocks.

Those schedules are driven by the ecosystems the components serve:

  • Helidon Core follows Java’s release cadence.
  • Helidon MCP follows the MCP specification.
  • The LangChain4j integration follows the LangChain4j project.
  • Helidon MicroProfile follows MicroProfile and the underlying Jakarta specifications.

Following Java’s predictable six-month release cadence for Helidon Core enables us to plan for and adopt new JDK features as soon as they become available, without waiting for the next major Helidon release. MCP, by contrast, is younger and less predictable. Helidon MCP needs to respond when the protocol specification changes rather than waiting for the next Core release.

Press enter or click to view image in full size
MCP release cadence

Similarly, MicroProfile and Jakarta evolve through deliberate specification processes whereas LangChain4j moves considerably faster, often publishing a new version every few weeks.

LangChain4j release cadence

The difference matters. Trying to keep all of these projects on one release train creates an awkward choice: make the slower-moving parts release unnecessarily often, or make the faster-moving integrations wait.

Helidon extensions can now update their dependencies, complete compatibility testing, and release according to the ecosystems they serve. Helidon Core can follow Java, while integrations such as MCP and LangChain4j move when their projects require it. Just as importantly, this structure gives us a clear way to add extensions for new ecosystems without folding them into Core or tying them to Core’s release cadence.

Declarative APIs: Full House.

Helidon 27 completes the Declarative API surface by adding the four remaining modules:

  • gRPC
  • Messaging
  • GraphQL
  • OpenAPI

Developers no longer need to leave the Declarative programming model simply because an application needs one of these features.

The coverage is complete, but the Declarative APIs are not yet final. They will remain in Preview until Helidon 29 LTS. This gives you a complete programming model to exercise in meaningful applications while still giving us room to respond to your feedback. Try the APIs with real workloads and tell us where the model is clear, where it gets in the way, and where an escape hatch is still required.

Your move.

Helidon Messaging Rewired

Messaging starts with three verbs: receive, process, send. However, it rarely stays that simple.

Helidon 27 takes a more direct route with Helidon Messaging, a new Helidon messaging module.

It simplifies messaging by avoiding reactive APIs and constructs such as MicroProfile Reactive Messaging. The messaging code you write in your applications is ordinary, blocking Java that works with logical channels. Configuration binds those channels to Kafka, JMS, or Pulsar through pluggable connectors.

Press enter or click to view image in full size
Helidon Messaging Architecture

There are three concepts worth keeping in mind:

  • A channel is a logical name used by the application.
  • A destination is the transport-specific endpoint, such as a Kafka or Pulsar topic, or a JMS queue or topic.
  • A connector bridges the two.

Consider an application that validates orders. The following diagram uses Kafka, but the application works with channels rather than Kafka topics:

Press enter or click to view image in full size
Messaging flow

The application code is pleasantly straightforward:

@Service.Singleton
final class OrderValidator {
@Messaging.ReceiveFrom("orders")
@Messaging.SendTo("validated-orders")
String validate(String order) {
// Business logic goes here
return order;
}
}

ReceiveFrom identifies the incoming orders channel. SendTo identifies the outgoing validated-orders channel. The method accepts and returns ordinary Java types: its declaration contains no consumer, producer, or reactive-stream types, and its body contains no Kafka, JMS, or Pulsar API calls.

However, the code is only half of the story. Configuration supplies the transport details:

messaging:
connector:
helidon-kafka:
bootstrap.servers: "localhost:9092"
incoming:
orders:
connector: helidon-kafka
topic: orders
group.id: order-validator
auto.offset.reset: earliest
outgoing:
validated-orders:
connector: helidon-kafka
topic: validated-orders
properties:
acks: all

This configuration binds the incoming orders channel to a Kafka topic and the outgoing validated-orders channel to another Kafka topic. It also specifies the broker address, consumer group, offset policy, acknowledgements, and the other details Kafka quite reasonably insists upon knowing.

Kafka is the choice made by this configuration, not by the application. The same channels could instead be bound to JMS queues or topics, or to Pulsar topics. Each transport retains its own capabilities and configuration model. Those differences remain in the connectors and configuration, while the business method remains concerned only with its business logic. That is enough responsibility for one method.

While the Java code describes the message flow, the configuration selects and tunes the transport. Changing transports does not require removing transport-specific APIs from the business method, because they were never there in the first place.

At runtime, the incoming connector consumes from its configured destination and exposes each value through the logical orders channel. Helidon invokes validate, routes the result through validated-orders, and the outgoing connector sends it to its configured destination.

Helidon validates the declarations and bindings as it assembles the end-to-end flow, allowing configuration problems to be detected before messages begin moving through the application.

The neat thing about pluggable connectors is that you can write your own. This is helpful in two situations:

  1. you need capabilities for an existing Helidon connector but these capabilities do not yet exist in Helidon’s connector e.g. you want to write a better Pulsar connector than the one we currently have.
  2. you need a connector for a messaging system for which we do not yet have one. We may want to build one in the future but you need it now.

The pluggable connector system enable you to build your own and use it with your application.

Until now, Helidon has supported only JMS and Kafka as messaging providers. With the new Helidon Messaging and the pluggable connector model, we have also added support for Pulsar. Admittedly, this is the first time we are adding support for Pulsar so there are probably things that we can improve.

Helidon Messaging is available as a Preview feature in Helidon 27. Try it with your workloads and tell us what works — and, more importantly, what does not. Your feedback will help us harden it before Helidon 29 LTS.

Helidon Data JDBC: SQL is inevitable.

Java developers are not short of ways to work with a relational database. There is JDBC for direct control, libraries that provide a more convenient layer over JDBC, SQL DSLs and query builders, repository frameworks, and full object-relational mapping. Each approach solves a different problem and makes a different set of trade-offs.

Helidon Data already offers one of those paths. Its repository model supports Jakarta Persistence (JPA), using EclipseLink or Hibernate as the ORM provider.

Helidon 27 adds another path: Helidon Data JDBC.

When you work with relational databases, SQL is a bit like Thanos. Abstractions can hide SQL, generate it, or leave it. What they cannot do is make it disappear.

Dread it. Run from it. SQL arrives all the same.

With Helidon Data JDBC, you own (and write) the SQL and the repository contract. Helidon generates the JDBC plumbing at build time. At runtime, that code binds the parameters, executes the statement, maps the result, and closes the resources when done.

A repository is a normal Java interface:

@Data.Repository
@Data.PersistenceUnit("contacts")
public interface ContactRepository {
@Jdbc.Statement("""
SELECT ID AS id, NAME AS name
FROM CONTACT
WHERE ID = :id
""")
@Jdbc.Execution(Jdbc.ExecutionType.QUERY)
Optional<ContactSummary> findById(long id);

@Jdbc.Statement("""
UPDATE CONTACT
SET STATUS = :status
WHERE ID = :id
""")
@Jdbc.Execution(Jdbc.ExecutionType.UPDATE)
long updateStatus(long id, String status);
}

The annotations select the JDBC provider and the contacts persistence unit. Each repository method declares the exact statement it executes.

findById binds the id parameter and maps the result to an Optional<ContactSummary>. updateStatus binds id and status, executes the update, and returns the number of affected rows.

There is no implementation class to write. Helidon generates it at build time.

Compared with the JPA path, the JDBC provider removes the ORM implementation and its runtime machinery from the stack. That means fewer runtime dependencies and fewer moving parts. There is no persistence context, dirty checking, lazy loading, or managed-entity lifecycle. Query results are plain Java values.

There is also no generated query quietly replacing the statement you thought you were running. The SQL you declare is the statement Helidon executes, creating a direct line between a production query and the repository method that owns it.

That gives application developers and database specialists something rather useful: the same SQL. They can review, troubleshoot, and tune the exact statement together without first reverse-engineering something produced by an ORM.

Explicit SQL also leaves the choice of database capabilities with you. You can write portable SQL when portability matters, or use vendor-specific syntax, functions, hints, or other features when they earn their place.

Helidon Data JDBC will not make a bad query good. It will make it considerably harder for that query to hide.

Helidon Data JDBC is available as an Incubating feature in Helidon 27.

Other Enhancements

Messaging and Data JDBC are the headline additions, but they are not travelling alone. Helidon 27 includes enhancements and new features across configuration, routing, TLS, telemetry, and JSON.

TOML Joins the League of Extraordinary Configuration Formats

Helidon Configuration already has an accomplished cast: properties, YAML, JSON, and HOCON. With Helidon 27, TOML joins them. Add helidon-extensions-toml-config and Helidon automatically discovers application.toml as a configuration source. The extension includes its own parser and document model, supports TOML 1.0 and 1.1, and introduces no external TOML-library dependency.

Dynamic Resource Matching: The Request Decides.

Most routes are decided when the server starts. That’s sensible and efficient but occasionally insufficient.

Sometimes the path is known, but the service behind it depends on information available only when the request arrives — an API version, tenant, item type, or application metadata that has changed since startup.

Applications could always intercept the request and implement their own dynamic routing logic. Helidon 27 makes that decision part of the framework instead.

Consider an Avengers mission dispatcher. The first path segment identifies the Avenger, while the selected service handles the remaining mission path:

HttpService ironManService =
rules -> rules.get("/{mission}", (req, res) -> {
String mission = req.path()
.pathParameters()
.first("mission")
.orElseThrow();
res.send("Iron Man reporting for " + mission);
});

HttpService thorService =
rules -> rules.get("/{mission}", (req, res) -> {
String mission = req.path()
.pathParameters()
.first("mission")
.orElseThrow();
res.send("Thor reporting for " + mission);
});

var avengers = Map.of(
"iron-man", ironManService,
"thor", thorService);

HttpRouting routing = HttpRouting.builder()
.registerLocator("/{avenger}", request -> request.path()
.pathParameters()
.first("avenger")
.map(avengers::get))
.build();

registerLocator associates the /{avenger} path pattern with a locator that runs for every matching request. For /iron-man/save-new-york, the locator extracts iron-man and returns ironManService. That service then handles the remaining /save-new-york path using its own /{mission} route. A request to /thor/defend-asgard follows the same path through thorService.

If the first path segment does not identify an available Avenger, the lookup produces an empty Optional and Helidon continues evaluating the remaining routes.

The significant part is when the service is selected. Conventional routing binds a service to a path when the server starts. HttpServiceLocator allows Helidon to select the service when the request arrives, using both the request and the application’s current state.

The locator decides which service receives the request. The selected HttpService retains its own routes, handlers, and lifecycle.

Helidon configures each distinct located service lazily and caches its routes by service instance. Later requests that select the same service reuse those routes.

Use conventional routing when the service is known at startup. Use a locator when selecting the service genuinely depends on the request or current application state. A dynamic feature is not obliged to make every route dynamic.

SNI: One Port, Many Identities.

TLS has a timing problem.

The server must choose a certificate during the handshake, before it receives the HTTP request. When several hostnames share the same port, the server needs to know which identity the client expects.

Server Name Indication, or SNI, supplies that information.

Helidon 27 adds first-class SNI configuration to both WebServer and WebClient.

A WebServer can associate different TLS certificates with virtual hosts on the same listener using exact hostnames or wildcard patterns. Applications can also decide whether a missing or unrecognized SNI name should use the listener’s default certificate or be rejected.

The virtual host selects the TLS certificate. The service continues to use its normal HTTP routing.

WebClient can obtain the SNI name from the request URI, the effective Host header, or an explicitly configured hostname. This behaviour is available across HTTP/1.1, HTTP/2, gRPC, and JSON-RPC clients.

The result is straightforward: several secure identities can share one listener, with hostname-based certificate selection and an explicit policy for missing or unrecognized names.

OpenTelemetry: Quieter Startup, Same Configuration

Helidon already supports HTTP request metrics aligned with OpenTelemetry semantic conventions.

Applications could previously start successfully while still reporting misleading warnings because several Helidon integrations attempted to register the global OpenTelemetry instance.

Helidon 27 changes those integrations so they coordinate and reuse the global instance where appropriate.

For affected applications, upgrading removes the misleading warnings and provides consistent telemetry initialization. No application changes are required.

Helidon JSON: From Library to Foundation

Helidon 4.4 introduced Helidon JSON, a build-time JSON binding library that generates type-safe, readable Java source and requires no runtime reflection.

Performance was one of its original goals. In the internal benchmarks published with Helidon 4.4, Helidon JSON recorded a 338% throughput improvement over Jackson for a representative basic document and also maintained its advantage when processing collections. As always, performance varies with payload shape, configuration, and workload.

Helidon 27 takes the next step by using Helidon JSON throughout Helidon Core. Eighteen components — including JSON-RPC, observability, security, MongoDB, configuration metadata, and several cloud integrations — have moved from JSON-P, Parsson, or HSON to Helidon JSON.

This reduces the number of JSON implementations used inside Helidon Core and removes those dependencies from the migrated components. It also expands the use of Helidon JSON’s build-time, reflection-free model throughout the framework.

Applications remain free to use JSON-P, JSON-B, Jackson, or another JSON library. Helidon using its own JSON implementation internally does not dictate which library your application must use.

HTTP/3 Begins

Press enter or click to view image in full size

Helidon’s HTTP/3 work has begun.

HTTP/3 carries HTTP over QUIC rather than TCP. QUIC supports independent streams and can reduce connection-establishment time. Because streams are independent, packet loss affecting one stream does not necessarily stall the others.

This is a substantial change to the transport beneath HTTP, and we want to explore what it can offer Helidon applications.

To be clear, HTTP/3 is not part of Helidon 27.

An early implementation is being prepared as a pre-Incubator project. When it becomes available, we want developers to build it, test it against real networks and workloads, and tell us where it behaves well — and where it does not.

That evidence will help us decide what HTTP/3 needs before it can become a supported Helidon feature.

Your Turn

With Tip-and-Tail, Helidon 27 begins a new chapter. It enables Helidon to move with Java, completes Declarative coverage, and puts new features such as Helidon Messaging and Helidon Data JDBC into your hands while there is still time for your feedback to shape them.

If you need a long-lived production baseline, Helidon 4.5 LTS remains the choice. If you want to follow the latest Java release, explore the complete Declarative model, or help shape Messaging and Data JDBC, take Helidon 27 for a spin.

Try the new APIs with your workloads. Test the connectors you use. Run your SQL. Exercise the edges rather than only the happy path. Then tell us what worked, what surprised you, and what made you reach for a debugger.

I want to conclude by thanking the Helidon engineering team. This is a team that packs a wallop and yet delivers with the minimum of fuss. To the team: you are amazing. Thank you.

--

--

Helidon
Helidon

Published in Helidon

The official project Helidon blog containing articles from Helidon developers and the developers community. All articles are approved by the Helidon team.