NioFlow is designed around one principle: make HTTP internals understandable without sacrificing production behavior. Instead of hiding complexity behind annotations and reflection-heavy bootstrapping, NioFlow keeps transport, parsing, routing, middleware, and error handling explicit and testable.
- What NioFlow Is
- Key Capabilities
- Quick Start
- Framework Programming Model
- Advanced Feature Pack
- Architecture Deep Dive
- Security Model
- Configuration Matrix
- Deployment Guide
- Repository Structure
- Roadmap for Production Hardening
NioFlow is a two-part system:
nioflow-framework: reusable HTTP framework module.task-planner-app: reference application that demonstrates how to use the framework in a real service.
It sits between "build a server from scratch" and "adopt a massive framework":
| Concern | NioFlow Approach | Why It Matters |
|---|---|---|
| Connection accept | NIO selector loop | High connection scalability with low idle overhead |
| Request handling | Bounded worker pool | Predictable behavior under load |
| Routing | Explicit code-based routes | Easy debugging and refactoring |
| Middleware | Global + route-group scoped | Clear policy layering (auth, rate limits, CORS) |
| Errors | Per-type handlers + global fallback | No stack trace leakage |
| Shutdown | Graceful draining via drainAndStop |
Safer rolling restarts |
NioFlowApp app = new NioFlowApp();
app.get("/", ctx -> ctx.send("Hello"));
app.get("/api/tasks/:id", ctx -> {
long id = ctx.pathParamAsLong("id"); // Safe numeric parsing
// ...
});
app.group("/api/admin", group -> {
group.use(new AuthMiddleware());
group.get("/stats", adminController::stats);
});app.use(new LoggerMiddleware());
app.use(new CorsMiddleware("https://yourdomain.com"));
app.use(new RateLimitMiddleware(100, 10_000));Middleware executes in registration order and is wrapped around each resolved route handler.
app.exception(IllegalArgumentException.class, (e, ctx) -> {
ctx.status(400).json(Map.of("error", "Bad Request", "details", e.getMessage()));
});
app.onError((err, ctx) -> {
ctx.status(500).json(Map.of("error", "Internal Server Error"));
});app.listenSecure(443, "keystore.jks", "changeit");
Runtime.getRuntime().addShutdownHook(
new Thread(() -> app.drainAndStop(30, TimeUnit.SECONDS))
);The NioFlow CLI handles scaffolding, environment setup, and hot-reloading for you. Requires Node.js (for the installer) and JDK 17+.
npm install -g @jhanvi857/nioflow-cli
# Create a project
nioflow new my-app
cd my-app
# Start with hot-reload
nioflow devNote: Node.js is only used to distribute the CLI. Your application runs purely on Java.
- JDK 17+
- Maven 3.9+
Create a local .env from the example and set a strong JWT secret:
cp .env.example .envWindows PowerShell alternative:
Copy-Item .env.example .envAt minimum, set:
JWT_SECRET(32+ characters)NIOFLOW_CORS_ORIGIN(frontend origin)DB_PASS(ifNIOFLOW_ENABLE_DB=true)
# From repository root
./mvnw clean testWindows PowerShell alternative:
.\mvn.ps1 clean test./mvnw exec:java -pl task-planner-app \
-Dexec.mainClass=io.github.jhanvi857.taskplanner.DemoApplication \
-Dnioflow.jwtSecret=your-very-long-secret-at-least-32-charscurl http://localhost:8080/_health
curl http://localhost:8080/_ready
curl http://localhost:8080/metrics
curl http://localhost:8080/api/tasks/Expected behavior:
/_healthreturns200with JSON payload./_readyreturns200when dependencies are ready./metricsreturns200(requiresNIOFLOW_METRICS_TOKENif configured)./_replayreturns401without bearer token (now auth-gated)./api/tasks/returns401without bearer token.
public class MyService {
public static void main(String[] args) {
NioFlowApp app = new NioFlowApp();
app.use(new LoggerMiddleware());
app.use(new CorsMiddleware("https://yourdomain.com"));
app.get("/", ctx -> ctx.send("Service up"));
app.group("/api/private", group -> {
group.use(new AuthMiddleware());
group.get("/profile", profileController::getProfile);
});
app.onError((err, ctx) -> {
ctx.status(500).json(Map.of("error", "Internal Server Error"));
});
Runtime.getRuntime().addShutdownHook(
new Thread(() -> app.drainAndStop(30, TimeUnit.SECONDS))
);
app.listen(8080);
}
}app.get("/api/tasks/:id", ctx -> {
long id = ctx.pathParamAsLong("id"); // Type-safe and injection-resistant
String auth = ctx.header("Authorization");
ctx.status(200).json(Map.of(
"taskId", id,
"authorized", auth != null
));
});public CompletableFuture<Optional<Task>> findById(Long id) {
return CompletableFuture.supplyAsync(() -> {
// Blocking JDBC work isolated in dedicated DB executor
// so request workers are not permanently blocked by DB I/O.
}, dbExecutor);
}NioFlow now includes six opt-in features designed for small teams operating production services without heavy platform infrastructure.
app.use(
new ChaosMiddleware()
.latency(200, 0.10)
.error(500, 0.05)
.drop(0.01)
);- Guarded by
NIOFLOW_CHAOS_ENABLED=true. - Logs each injected fault with route and path.
- Supports composable latency, error, and drop behavior.
app.get("/api/orders", ordersController::list)
.timeout(2000)
.rateLimit(50, 10_000);- Per-route request/error counters.
- Per-route p50/p95/p99 latency (sliding in-memory window).
- Route-scoped timeout and route-scoped rate limit.
app.get("/api/search", searchController::search)
.hedge(100);- Fires a backup execution when primary crosses threshold.
- Returns first successful completion.
- Hedge trigger count appears in route-level metrics.
app.group("/api/downstream", group -> {
group.use(new CircuitBreakerMiddleware()
.threshold(0.5)
.windowSize(20)
.cooldown(10_000));
group.get("/inventory", inventoryController::read);
});- CLOSED / OPEN / HALF_OPEN states.
- OPEN returns
503andRetry-Afterheader. - Circuit state is exposed per route-group in
/metricsoutput.
app.enableReplay(50);- Guarded by
NIOFLOW_REPLAY_ENABLED=true. - Captures recent requests in circular memory buffer.
GET /_replaylists recorded requests.POST /_replay/:indexreplays through current live pipeline.- Sensitive headers (Authorization, Cookie, X-API-Key, Proxy-Authorization) are stripped automatically.
- SECURITY: The replay endpoints are now protected by
AuthMiddlewareby default. Only authenticated users with valid JWTs can access request history.
NioFlowApp.enableHotReload(DemoApplication.class, args);- Guarded by
NIOFLOW_WATCH=true. - Monitors source directory for changes.
- Automatically recompiles using Maven (
mvn,mvnw, ormvn.ps1). - Restarts the application in a child process for near-instant developer feedback.
graph TD
C[Client] --> SEL[Selector Accept Loop]
SEL --> ACC[Accept SocketChannel]
ACC --> BLK[Configure blocking mode for worker parsing]
BLK --> WP[Bounded Worker Pool]
WP --> HP[HttpParser]
HP --> RT[Router]
RT --> MW[Middleware Chain: Logger, Tracing, CORS]
MW --> CB{Circuit Breaker?}
CB -- OPEN --> 503[503 Service Unavailable]
CB -- CLOSED --> H[Route Handler]
H --> RESP[HttpResponse]
RESP --> C
H --> DB[(PostgreSQL / Mongo / Redis)]
H --> OT[OpenTelemetry Exporter]
RT --> PLG[Plugins: HealthCheck, StaticFiles, Replay]
sequenceDiagram
participant Client
participant Worker
participant Router
participant Middleware
participant Handler
Client->>Worker: TCP Connection
Worker->>Worker: Parse HTTP Request
Worker->>Router: Resolve Route
alt Route Not Found
Router-->>Client: 404 Not Found
else Method Not Allowed
Router-->>Client: 405 Method Not Allowed
else Success
Router->>Middleware: Execute Global + Group Hooks
Middleware->>Handler: Execute Handler (wrapped in CB/Hedge)
Handler-->>Client: 200/201/204 Response
end
- Accept path: NIO selector thread.
- Request work path: bounded worker pool.
- Database path: dedicated DB executor pool.
This split protects the server from unbounded queue growth and improves backpressure behavior under load.
- Protected route groups use
AuthMiddleware. - Token format:
Authorization: Bearer <jwt>. - JWT key source:
JWT_SECRET(env) or-Dnioflow.jwtSecret=.... - Startup behavior in reference app: exits if JWT secret is missing or too short.
| Control | v1.4.0 Hardening Behavior |
|---|---|
| Header size cap | 8 KB maximum |
| Body size cap | 10 MB maximum |
| HTTP Smuggling | Rejects obfuscated Transfer-Encoding (e.g. "identity, chunked") |
| Injection | Rejects CRLF in headers and Null bytes in paths |
| Rate limiting | Hardened IP extraction (Socket Peer fallback) |
| JWT Security | Mandatory issuer validation and high-entropy secret check |
| Error responses | Sanitized with generic messages in production |
| Code Coverage | 83.44% Instructions, 71.69% Branches (Enforced by JaCoCo) |
NioFlow maintains a rigorous testing strategy to ensure framework stability and security. All pull requests are gated by a JaCoCo coverage check in the build pipeline.
| Package | Instruction Coverage | Branch Coverage | Focus |
|---|---|---|---|
.protocol |
~89% | ~89% | HTTP Parsing & Smuggling defenses |
.routing |
~85% | ~80% | Route matching & parameter extraction |
.middleware |
~85% | ~80% | Auth, RateLimit, Metrics |
.util |
~92% | ~85% | JSON, Env, Internal helpers |
.plugin |
~75% | ~70% | StaticFiles, HealthChecks |
| TOTAL | 83.44% | 71.69% | Project Baseline |
To execute the full test suite and generate a coverage report:
mvn clean testThe report is generated at nioflow-framework/target/site/jacoco/index.html.
String corsOrigin = System.getenv("NIOFLOW_CORS_ORIGIN");
if (corsOrigin == null || corsOrigin.isBlank()) {
corsOrigin = "http://localhost:3000";
}
app.use(new CorsMiddleware(corsOrigin));For production, always set NIOFLOW_CORS_ORIGIN to your exact frontend origin.
| Variable / Property | Required | Default | Purpose |
|---|---|---|---|
PORT |
No | 8080 |
Server port |
JWT_SECRET |
Yes unless auth disabled | None | JWT secret used by AuthMiddleware |
NIOFLOW_DISABLE_AUTH |
No | false |
Disable JWT checks for protected groups (dev only) |
NIOFLOW_CORS_ORIGIN |
Recommended | http://localhost:3000 |
CORS allow-origin value |
NIOFLOW_ENABLE_DB |
No | false |
Enables DB-backed readiness checks and repository behavior |
JDBC_URL |
If DB enabled | jdbc:postgresql://localhost:5432/nioflow |
PostgreSQL URL |
DB_USER |
If DB enabled | postgres |
PostgreSQL user |
DB_PASS |
If DB enabled | None | PostgreSQL password |
MONGO_URI |
No | None | Optional MongoDB URI (enables initMongo) |
NIOFLOW_THREADS / nioflow.threads |
No | 64 |
Worker pool size in HttpServer |
NIOFLOW_QUEUE_CAPACITY / nioflow.queueCapacity |
No | 1000 |
Worker queue capacity for backpressure |
NIOFLOW_SOCKET_TIMEOUT_MS / nioflow.socketTimeoutMs |
No | 30000 |
Socket read timeout per connection |
NIOFLOW_TLS_ENABLED |
No | false |
Enable native TLS listener |
NIOFLOW_TLS_KEYSTORE_PATH |
If TLS enabled | None | JKS keystore path |
NIOFLOW_TLS_KEYSTORE_PASSWORD |
If TLS enabled | None | Keystore password |
NIOFLOW_TLS_PORT |
No | 8443 |
Native TLS listener port |
NIOFLOW_EXPOSE_ERROR_DETAILS |
No | false |
Include exception details in error payloads |
NIOFLOW_STATIC_DIR / nioflow.staticDir |
No | Auto-resolve | Static files directory |
NIOFLOW_CHAOS_ENABLED |
No | false |
Enables ChaosMiddleware fault injection |
NIOFLOW_REPLAY_ENABLED |
No | false |
Enables enableReplay(...) endpoints |
NIOFLOW_WATCH |
No | false |
Enables nodemon-like hot reload (Watch Mode) |
NIOFLOW_LOG_FORMAT |
No | plain |
Set to json for structured logging |
NIOFLOW_REDIS_URL |
No | None | Redis connection string for distributed rate limiting |
NIOFLOW_TRACING_ENABLED |
No | false |
Enables OpenTelemetry tracing |
NIOFLOW_METRICS_TOKEN |
No | None | Optional bearer token gate for /metrics |
NIOFLOW_JWT_EXPIRATION_MS |
No | 900000 (15m) |
JWT access token lifetime |
OTEL_EXPORTER_OTLP_ENDPOINT |
No | http://localhost:4317 |
OTLP gRPC collector endpoint |
NioFlow provides a centralized Database utility to manage your persistence layers with zero boilerplate.
Initialize and get connections directly:
NioFlowApp app = new NioFlowApp();
// Reads JDBC_URL from .env
app.initPostgres();
try (Connection conn = Database.getPostgresConnection()) {
// Standard JDBC logic
}Initialize and access the document store:
// Reads MONGO_URI from .env
app.initMongo();
MongoClient mongo = Database.getMongoClient();
MongoDatabase db = mongo.getDatabase("nioflow");NioFlow includes a built-in Env utility that automatically loads configuration from a .env file in your project root. This ensures that sensitive keys (like Supabase secrets) remain safe and are not passed via command line arguments.
Example .env file:
JDBC_URL=jdbc:postgresql://your-db.supabase.co:5432/postgres
DB_USER=postgres
DB_PASS=your-password
JWT_SECRET=your-32-char-secret
PORT=8080./mvnw package -DskipTests -pl task-planner-app -amPrimary runnable artifact:
task-planner-app/target/task-planner-app-1.0-SNAPSHOT-jar-with-dependencies.jar
With the new .env support, you no longer need complex -D flags:
java -jar task-planner-app/target/task-planner-app-1.0-SNAPSHOT-jar-with-dependencies.jar- Global
onErrorhandler registered. - Graceful shutdown hook registered.
- Protected routes gated by
AuthMiddleware. - JWT secret validated at startup.
- Integration tests assert auth enforcement and observability endpoints.
- Integration tests assert 404 vs 405 distinction.
- Integration tests assert middleware ordering and header preservation.
- Integration tests assert circuit breaker state transitions (CLOSED → OPEN → HALF_OPEN → CLOSED).
- TLS plan finalized (
listenSecureor reverse proxy termination). - Runtime sizing validated with reproducible load testing script (
scripts/k6-load-test.js). - Vulnerability scanning is enforced in CI for push/PR (
OWASP Dependency Check).
NioFlow is designed for high-performance NIO-based request handling. Below are the results of a standardized load test conducted against the task-planner-app reference implementation.
- Tooling: k6 v1.7.1
- Endpoint:
GET /_health(unauthenticated) - Profile: Graduated ramp-up from 0 to 100 Virtual Users (VUs) over 2 minutes.
- Hardware: Local execution on Windows (Consumer-grade CPU/RAM).
| Metric | Result |
|---|---|
| Throughput | 501.12 requests/second |
| Median Latency (p50) | 1.52 ms |
| p95 Latency | 47.75 ms |
| p99 Latency | 74.62 ms |
| Success Rate | 99.84% (0.16% error rate at peak 100 VUs) |
.
├── nioflow-framework/
│ └── src/main/java/io/github/jhanvi857/nioflow/
│ ├── auth/ # JWT provider and auth primitives
│ ├── exception/ # Exception handlers and mapping
│ ├── middleware/ # Logger, CORS, auth, rate limit, metrics
│ ├── observability/ # Health handlers
│ ├── plugin/ # Plugin registration points
│ ├── protocol/ # Parser, request, response models
│ ├── routing/ # Route, router, groups, context
│ └── server/ # NIO accept loop and connection handlers
│
├── task-planner-app/
│ └── src/main/java/io/github/jhanvi857/taskplanner/
│ ├── controller/ # HTTP-facing handlers
│ ├── repository/ # JDBC access wrapped in futures
│ ├── db/ # Hikari and DB bootstrap
│ └── DemoApplication.java
│
├── documentation/nioflow/ # Next.js documentation portal
├── .github/workflows/ # CI build/test/security checks
├── Dockerfile # Multi-stage image build
├── docker-compose.yml # App + Postgres local stack
└── runbook.md # Operational procedures
This project is authored and maintained by Jhanvi Patel (jhanvi857).
- Environment Management: Powered by dotenv-java by io.github.cdimascio. Licensed under the Apache License 2.0.
- Networking: Core architectural patterns for the NIO engine were derived from industry-standard high-performance Java server implementations. We honor all original authors and adhere to open-source compliance.
This project is licensed under the MIT License - see the LICENSE file for details.
