Hiver is an alpha-stage web framework written in Rust with a custom async runtime, aiming to mirror the Spring ecosystem. Unlike other frameworks that use Tokio, Hiver features a custom async runtime built from scratch using io-uring for maximum performance. Not yet production-ready (0.1.0-alpha.6) — see project status.
- Custom Runtime - Thread-per-core architecture with io-uring support
- Spring-like Annotations -
#[controller],#[service],#[repository],#[autowired],#[transactional],@Cacheable,@PreAuthorize, and 40+ more - Data Layer - R2DBC, ORM (ActiveRecord), Redis, MongoDB, Flyway migrations, JPA-style
#[Entity]/#[Table]/#[Id]/#[Column] - AI Integration - OpenAI, Anthropic, Ollama chat models; embeddings; vector store; function calling
- Messaging - Kafka, AMQP/RabbitMQ, Spring Events, Spring Integration EIP patterns
- Cloud - Service discovery, load balancer, gateway, config server, Feign client
- Security - JWT, OAuth2 Authorization Server, RBAC, CSRF,
@PreAuthorize,@Secured - High Availability - Circuit breakers, rate limiters, retry logic
- Web3 Native - Built-in blockchain and smart contract support (ERC20/ERC721)
- Observability - Distributed tracing, Micrometer-compatible metrics, OpenAPI/Swagger
- Enterprise - Batch processing, state machine, LDAP, Vault, SOAP WS, GraphQL, gRPC, i18n
- Tooling - Lombok-style derive macros, Spring Shell REPL, test containers, mock beans
Add to your Cargo.toml:
[dependencies]
# Published to crates.io (0.1.0-alpha.6)# 已发布到 crates.io(0.1.0-alpha.6)hiver-runtime = "0.1.0-alpha.6"hiver-http = { version = "0.1.0-alpha.6", features = ["full"] }
hiver-router = "0.1.0-alpha.6"hiver-observability = "0.1.0-alpha.6"use hiver_http::{Body,Response,Server,StatusCode};use hiver_runtime::Runtime;fnmain() -> Result<(),Box<dyn std::error::Error>>{// Initialize logging
tracing_subscriber::fmt().with_max_level(tracing::Level::INFO).init();// Create runtime and run serverletmut runtime = Runtime::new()?;
runtime.block_on(async{// Bind server to addresslet _server = Server::bind("127.0.0.1:8080").run(handle_request).await?;Ok::<_,Box<dyn std::error::Error>>(())})}asyncfnhandle_request(req: hiver_http::Request) -> Result<Response, hiver_http::Error>{Ok(Response::builder().status(StatusCode::OK).header("content-type","text/plain").body(Body::from("Hello, Hiver!")).unwrap())}//! Hiver REST API Example//!//! This example demonstrates a complete REST API with://! - Routing with path parameters//! - JSON request/response//! - Error handling//! - Middleware (CORS, logging)//! - Circuit breaker//! - Observability (tracing, metrics)use hiver_http::{Body,Response,Server,StatusCode,Request,ResultasHttpResult,};use hiver_router::Router;use hiver_runtime::Runtime;use hiver_observability::{tracing, metrics};// ============================================================================// Data Models// ============================================================================/// User representation#[derive(Debug,Clone, serde::Serialize, serde::Deserialize)]structUser{id:u64,username:String,email:String,}/// Create user request#[derive(Debug, serde::Deserialize)]structCreateUserRequest{username:String,email:String,}// ============================================================================// Error Handling// ============================================================================/// API Error type#[derive(Debug)]enumApiError{/// User not found (404)UserNotFound(u64),/// Invalid input (400)InvalidInput(String),/// Internal server error (500)Internal(String),}implApiError{/// Convert to HTTP status codefnstatus_code(&self) -> StatusCode{matchself{ApiError::UserNotFound(_) => StatusCode::NOT_FOUND,ApiError::InvalidInput(_) => StatusCode::BAD_REQUEST,ApiError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,}}/// Get error messagefnmessage(&self) -> String{matchself{ApiError::UserNotFound(id) => format!("User {} not found", id),ApiError::InvalidInput(msg) => msg.clone(),ApiError::Internal(msg) => format!("Internal error: {}", msg),}}}// ============================================================================// In-Memory Store// ============================================================================/// Simple in-memory user storestructUserStore{users: std::sync::Arc<parking_lot::Mutex<std::collections::HashMap<u64,User>>>,next_id: std::sync::Arc<std::sync::atomic::AtomicU64>,}implUserStore{/// Create new storefnnew() -> Self{Self{users: std::sync::Arc::new(parking_lot::Mutex::new(std::collections::HashMap::new())),next_id: std::sync::Arc::new(std::sync::atomic::AtomicU64::new(1)),}}/// Get user by IDfnget(&self,id:u64) -> Option<User>{self.users.lock().get(&id).cloned()}/// Create new userfncreate(&self,req:CreateUserRequest) -> User{let id = self.next_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);let user = User{
id,username: req.username,email: req.email,};self.users.lock().insert(id, user.clone());
user
}/// List all usersfnlist(&self) -> Vec<User>{self.users.lock().values().cloned().collect()}}// ============================================================================// Route Handlers// ============================================================================/// GET /users - List all usersasyncfnlist_users(_req:Request,store: hiver_router::State<UserStore>,) -> HttpResult<Response>{
tracing::info!("Listing all users");let users = store.list();Ok(Response::builder().status(StatusCode::OK).header("content-type","application/json").body(Body::from(serde_json::to_string(&users).unwrap())).unwrap())}/// GET /users/:id - Get user by IDasyncfnget_user(req:Request,store: hiver_router::State<UserStore>,) -> HttpResult<Response>{// Extract path parameterlet id = req
.param("id").and_then(|s| s.parse::<u64>().ok()).ok_or_else(|| ApiError::InvalidInput("Invalid user ID".to_string()))?;
tracing::info!("Getting user: {}", id);// Look up userlet user = store
.get(id).ok_or_else(|| ApiError::UserNotFound(id))?;Ok(Response::builder().status(StatusCode::OK).header("content-type","application/json").body(Body::from(serde_json::to_string(&user).unwrap())).unwrap())}/// POST /users - Create new userasyncfncreate_user(mutreq:Request,store: hiver_router::State<UserStore>,) -> HttpResult<Response>{// Parse request bodylet body = std::pin::pin(&mut req).body_bytes().await.map_err(|e| ApiError::Internal(format!("Failed to read body: {}", e)))?;let create_req = serde_json::from_slice::<CreateUserRequest>(&body).map_err(|e| ApiError::InvalidInput(format!("Invalid JSON: {}", e)))?;
tracing::info!("Creating user: {}", create_req.username);// Validate inputif create_req.username.is_empty() || create_req.username.len() > 50{returnErr(ApiError::InvalidInput("Username must be 1-50 characters".into()).into());}// Create userlet user = store.create(create_req);Ok(Response::builder().status(StatusCode::CREATED).header("content-type","application/json").header("location",format!("/users/{}", user.id)).body(Body::from(serde_json::to_string(&user).unwrap())).unwrap())}// ============================================================================// Error Conversion// ============================================================================implFrom<ApiError>for hiver_http::Error{fnfrom(err:ApiError) -> Self{
hiver_http::Error::new(err.status_code(), err.message())}}// ============================================================================// Main Application// ============================================================================fnmain() -> Result<(),Box<dyn std::error::Error>>{// Initialize logging
tracing_subscriber::fmt().with_max_level(tracing::Level::INFO).init();// Create shared statelet store = UserStore::new();// Build routerlet app = Router::new()// GET /users - List users.route("/users", hiver_router::Method::GET, list_users)// GET /users/:id - Get user.route("/users/:id", hiver_router::Method::GET, get_user)// POST /users - Create user.route("/users", hiver_router::Method::POST, create_user)// Add state.with_state(store);// Create and run runtimeletmut runtime = Runtime::new()?;
tracing::info!("Starting server on http://127.0.0.1:8080");
runtime.block_on(async{// Start serverlet _server = Server::bind("127.0.0.1:8080").run(app).await?;Ok::<_,Box<dyn std::error::Error>>(())})}# List users (empty)
curl http://localhost:8080/users
# Create a user
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"username":"alice","email":"alice@example.com"}'# Get user by ID
curl http://localhost:8080/users/1
# List users (with data)
curl http://localhost:8080/usersHiver provides a unified logging system with two modes: Verbose (development) and Simple (production).
use hiver_observability::log::{Logger,LoggerConfig,LogLevel,LogMode};fnmain() -> Result<(),Box<dyn std::error::Error>>{// Automatic mode selection based on profilelet config = LoggerConfig{level:LogLevel::Info,mode:LogMode::from_profile(Some("dev")),// dev->Verbose, prod->Simple
..Default::default()};Logger::init_with_config(config)?;
tracing::info!("Application started");Ok(())}Configuration via Environment Variables:
# Set log levelexport HIVER_LOG_LEVEL=DEBUG
# Set log mode explicitlyexport HIVER_LOG_MODE=simple # or "verbose"# Set profile (affects default mode)export HIVER_PROFILE=prod # dev->verbose, prod->simpleOutput Comparison:
| Mode | Format |
|---|---|
| Verbose (dev) | 2026-01-30 10:30:45.123 |INFO| 55377 [main] n.http.server : Request received |
| Simple (prod) | INFO n.http.server: Request received |
use hiver_resilience::{CircuitBreaker,RateLimiter,RetryPolicy};use hiver_http::Request;// Circuit breakerlet breaker = CircuitBreaker::new("external-api",5,// failure threshold10000,// timeout ms);// Rate limiterlet limiter = RateLimiter::token_bucket(100,10);// 100 requests, refill 10/sec// Retry with exponential backofflet retry = RetryPolicy::exponential_backoff(3,100);// 3 retries, 100ms base// Use in handlerasyncfncall_external_api(req:Request) -> Result<Response,Error>{
breaker.call(|| async{
limiter.throttle().await?;
retry.retry(|| async{// Actual API callmake_request(req).await}).await}).await}use hiver_web3::{Chain,ChainConfig,LocalWallet,RpcClient,Transaction,TransactionBuilder,TxType,};asyncfnweb3_example() -> Result<(),Box<dyn std::error::Error>>{// Connect to Ethereumlet chain = Chain::ethereum();let rpc = RpcClient::new(&chain.rpc_url())?;// Create walletlet wallet = LocalWallet::new(&mut rand::thread_rng());// Build transactionlet tx = TransactionBuilder::new().to(wallet.address()).value(1000000)// 0.001 ETH.gas_limit(21000).chain_id(chain.chain_id()).build(TxType::Legacy)?;// Send transactionlet signed = wallet.sign_transaction(&tx)?;let tx_hash = rpc.send_raw_transaction(&signed).await?;
tracing::info!("Transaction sent: {}", tx_hash);Ok(())}Hiver is designed for high performance from the ground up:
- 70% fewer syscalls vs epoll with io-uring
- 40% lower latency with thread-per-core architecture
- Zero-copy I/O for minimal allocations
- Linear scalability with no lock contention
| Benchmark | Result |
|---|---|
| HTTP Parsing (GET) | ~170 ns |
| HTTP Encoding | ~120 ns |
| Throughput | 6.8 GiB/s |
| Spawn latency | < 1 μs |
| Channel throughput | 10M+ msg/s |
| Resource | Link |
|---|---|
| Codemap | CODEMAP.md — Full crate reference, macro index, dependency graph |
| Book | docs.hiverframework.com |
| API Docs | docs.rs/hiver |
| Design Spec | design-spec.md |
| Spring Comparison | SPRING-COMPARISON.md — Spring vs Hiver ecosystem comparison |
| Implementation Plan | implementation-plan.md |
| Docs Index | DOCS-INDEX.md |
| Examples | examples/ |
62 crates across 10 functional domains. See CODEMAP.md for the full reference.
hiver-starter (Spring Boot auto-configuration)
│
├── Web: hiver-http, hiver-router, hiver-extractors, hiver-middleware,
│ hiver-response, hiver-hateoas, hiver-multipart, hiver-openapi, hiver-graphql
├── Data: hiver-data-commons, hiver-data-rdbc, hiver-data-orm, hiver-data-redis,
│ hiver-data-mongodb, hiver-data-annotations, hiver-data-macros, hiver-flyway
├── Security: hiver-security, hiver-session
├── AOP: hiver-aop, hiver-tx
├── Messaging:hiver-events, hiver-events-macros, hiver-kafka, hiver-amqp,
│ hiver-integration, hiver-websocket-stomp
├── Infra: hiver-runtime, hiver-core, hiver-macros, hiver-lombok, hiver-config,
│ hiver-exceptions, hiver-spel
├── Cloud: hiver-cloud, hiver-ai, hiver-agent, hiver-web3, hiver-vault, hiver-ldap, hiver-grpc
├── Resilience:hiver-resilience, hiver-observability, hiver-micrometer, hiver-actuator,
│ hiver-retry, hiver-retry-macros
├── Enterprise:hiver-batch, hiver-state-machine, hiver-async, hiver-schedule, hiver-ws,
│ hiver-i18n, hiver-modulith
└── Tooling: hiver-test, hiver-shell, hiver-shell-macros, hiver-benches, hiver-validation,
hiver-validation-annotations, hiver-cache
# Clone repository
git clone https://github.com/ViewWay/hiver.git
cd hiver
# Build
cargo build --workspace
# Test
cargo test --workspace
# Run benchmarks
cargo bench -p hiver-runtime
# Format
cargo fmt --all
# Lint
cargo clippy --workspace -- -D warnings
⚠️ Alpha VersionHiver is alpha software (
0.1.0-alpha.6). Currently in Phase 8: Data Layer (in progress). Phases 0–7 feature work is done (code-level), but not production-stable. The custom async runtime is stable undercargo test --workspace(4 UBs fixed, Phase 0.1 complete). The framework spans 70 crates covering the Spring Boot feature surface. See verified gap report and roadmap.
| Phase | Status | Description |
|---|---|---|
| Phase 0 | ✅ Complete | Foundation |
| Phase 1 | ✅ Complete | Runtime Core |
| Phase 2 | ✅ Complete | HTTP Server |
| Phase 3 | ✅ Complete | Router & Middleware |
| Phase 4 | ✅ Complete | Resilience |
| Phase 5 | ✅ Complete | Observability |
| Phase 6 | ✅ Complete | Web3 Integration |
| Phase 7 | ✅ Complete | Performance & Hardening |
| Phase 8 | 🔄 In Progress | Data Layer (R2DBC, ORM, Redis, MongoDB, Flyway) — 8.1–8.3 core modules complete, structural refactoring ongoing |
See implementation plan for details.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Hiver is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
Hiver is inspired by excellent frameworks across multiple languages:
- Rust: Axum, Actix Web, Monoio, Salvo
- Go: Gin, Echo
- Java: Spring Boot, WebFlux
- Python: FastAPI, Starlette
Hiver Framework — Built for the future of web development.
