java-http, A Simple, Fast HTTP Server with Virtual Threads

java-http is a lightweight, zero-dependency Java HTTP server library that uses virtual threads to achieve 120,000+ requests per second with maintainable, synchronous-style code.

Authors

Published: October 6, 2025


You may not have previously considered the HTTP server when building a web application. It may already be packaged as part of an application server such as Apache Tomcat or Spring Boot.

If you were to try and hand pick an HTTP server to build your next app - you’ll find off the shelf options with various degrees of complexity and all of them requiring third-party dependencies.

What is java-http?

java-http is a lightweight, open-source, zero-dependency HTTP server for Java, licensed under Apache2. It’s designed to feel like it belongs in the JDK. This means, zero dependencies, pure Java, blazingly fast, and simple to use. Unlike other Java web servers that pull in third-party dependencies, by design java-http requires zero external dependencies.

Even the logger is your choice. Seriously, no deps. Log4j, Logback or standard out, dealers choice. Check out the build dependencies in the pom.

The library provides a straightforward API for creating HTTP servers with just a few lines of code. You can bind listeners, define handlers, and start serving requests without the configuration overhead of traditional application servers like Apache Tomcat. It supports route handlers similar to what you’d find in Node.js or Flask, making it a pleasant surprise for Java developers and familiar for those coming from other ecosystems.

Here’s an example which starts a server on port 4242:

import io.fusionauth.http.server.HTTPListenerConfiguration;
import io.fusionauth.http.server.HTTPServer;
import io.fusionauth.http.server.HTTPHandler;

public class Example {
  public static void main(String... args) {
    HTTPHandler handler = (req, res) -> {
      // Handler code goes here
    };

    HTTPServer server 
      = new HTTPServer().withHandler(handler)
                        .withListener(new HTTPListenerConfiguration(4242));
    server.start();
    // Use server
    server.close();
  }
}

java-http inverts the traditional Java web application model. Instead of your application being deployed into a container like Apache Tomcat, it becomes the main entry point and controls the HTTP server directly. This gives you complete control over startup and shutdown processes, environment variables, configuration files, and ports. These are all programmatically managed rather than constrained by external configuration files or what the container allows.

Why Does java-http Exist?

The Java ecosystem lacked a simple HTTP server.

Apache Tomcat has been one of the go-to choices for Java web applications. Tomcat can be slow to adopt new standards and adds significant complexity for simple use cases. Netty is another option, but has a sprawling feature set and is overly complex.

There are others, but nearly all of them come with dependencies, pulling in libraries for functionality that you may not need that can lead to version conflicts with your own dependencies. This bloat can slow down startup times, increase memory usage, and create potential security vulnerabilities through unused code paths.

The goal with this project was to create something that felt native to the JDK; a library that could serve as the foundation for web applications without the overhead of traditional application servers. By making the application itself the entry point, developers gain flexibility in how they structure and deploy their applications.

The purest ideal of a developer tool, or library is one that performs a function extremely well, and does not require any external dependencies. This allows you to add this library to your dependency graph w/out risk of conflicts or unexpected jars in your classpath.

This ideal was the true motivation for building java-http.

We originally built FusionAuth on top of Apache Tomcat. We kept having to work around the limitations of the Java Servlet spec and the subsequent adoption into Apache Tomcat.

If you don’t know what the Java Servlet spec is - ask someone old, grandpa, grandma, or your crazy programmer uncle. 😎

Case in point, the cookie SameSite attribute, a critical security feature for cookies first introduced in 2015 and supported by most browsers by 2017

This feature was officially added to the Servlet spec in version 6 which was released May 2022. Then supported by Apache Tomcat in version 10.1 which was released Sept 2022. A tight 5 years. This rate of adoption of web technology was not ideal for building a security product primarily for web application developers.

We ditched Apache Tomact some time ago, and spent some time with Netty, and while it was workable, the documentation was confusing, and in general was just overly complex for our use case.

We realized Netty was not the long term solution for us either, so we went back to basics.

Sometimes you need a fast, reliable HTTP server without all the bells and whistles. This library provides essential functionality needed to build robust web applications without unnecessary complexity.

A core principle at FusionAuth which is also true of java-http is to minimize dependencies; in this case there are none. As an attribute of any library you choose to use in development, this one is extremely under-rated.

Zero dependencies removes the risk of supply chain attacks. A zero-dependency approach also means you won’t need to worry about version conflicts or transitive dependency issues. This ideal is a reflection of our approach to building software: fast, purpose-built tools with as few dependencies as humanly possible.

Because you can download FusionAuth as a .zip, .deb, .rpm or a Docker image, keeping dependencies low is also practical as it means a faster download. Sometimes bigger is better, but for download sizes and classpaths, there is no shame in being small.

Performance: 120,000 Requests Per Second

Performance is also a core principle of java-http. In simplified benchmarks, a server can handle around 120,000 requests per second. The goal isn’t necessarily to be the fastest HTTP server in any language, but to be faster than other Java-based HTTP servers while maintaining simplicity.

This benchmark does not represent real world performance because the requests are small, and the latency is near zero. Instead this number represents the performance of the library itself after removing all variables outside of our control.

This benchmark proves that the HTTP server itself will not be your bottleneck.

In real-world applications, performance constraints typically lie elsewhere. This could be in database queries, external API calls, business logic, or cryptographic operations. By ensuring the HTTP layer can handle high throughput, you can focus your optimization efforts where they’ll have the most impact.

What’s new?

John Wick talking threads.

The largest recent change to java-http was the adoption of virtual threads, made possible by Java 21’s Project Loom. The first version of the library, released in 2022, used traditional NIO (non-blocking I/O), which was fast but resulted in complex, hard-to-maintain code with asynchronous operations scattered throughout. Adding new features or debugging issues required understanding complex state management and callback chains (“which socket am I thinking about now?”).

Leveraging virtual threads has allowed us to write code that looks and behaves like traditional threaded code while maintaining the performance benefits of asynchronous operations under the hood. The complexity of asynchronous programming is hidden from developers, making the codebase much easier to understand, debug, and extend. Developers can understand the code more quickly, bugs are easier to trace and fix, and adding new features becomes straightforward. Error handling is centralized in try-catch blocks rather than being scattered across multiple callback functions.

The transition to virtual threads didn’t present significant technical challenges. Code that was previously spread across multiple callbacks and state machines is now written as straightforward, linear functions that are much easier to reason about. There are some minor edge cases around socket exception handling, particularly when distinguishing between clean shutdowns and other exceptions such as those caused by client-side connection closures. These are manageable complexities that exist in any socket-based system.

There were some performance benefits as well, especially in constrained environments. For example, FusionAuth test suites that previously took two hours to complete in thread-limited environments like GitHub Actions have been cut in half due to the efficiency improvements that virtual threads provide.

Performance improvements might not always be visible on high-end development machines with abundant resources, however. Benefits are most pronounced where efficient thread utilization can make a significant difference in overall system performance.

And, as always, performance is context dependent.

How You Can Help

The easiest way to contribute to java-http is by using it.

Real-world usage provides valuable feedback about missing features, edge cases or bugs, and areas for improvement. The project maintainers prioritize this type of contribution because they are focused on concrete use cases and demonstrated needs. The project welcomes contributions, but focuses on keeping the core library slim, dependency-free, and purpose-built.

Getting started is straightforward. The project’s README provides clear examples showing how to create a server, bind listeners, and define handlers with just a few lines of code.

If you encounter issues or have ideas for improvements, the best approach is to open an issue or pull request on the GitHub repository.

Summing Up

java-http is production-ready and battle-tested at scale across multiple high-traffic applications, including FusionAuth. While it may not have the widespread adoption of more established alternatives like Netty or Tomcat, its use in production environments demonstrates its performance, stability and reliability.

Whether you’re building microservices, API servers, or simple web applications, java-http provides a solid foundation that gets out of your way and lets you focus on your application. Give it a try and help shape its future by sharing your experience and contributing to its development.

More on java

Subscribe to The FusionAuth Newsletter

Get updates on techniques, technical guides, and the latest product innovations coming from FusionAuth.

Just dev stuff. No junk.