Production Deployment Checklist for Hyperlane
Project Code:https://github.com/hyperlane-dev/hyperlane
Introduction
Deploying a hyperlane application to production requires careful planning across multiple dimensions: security, performance, monitoring, and infrastructure. Hyperlane is a lightweight, high-performance, cross-platform Rust HTTP server library built on Tokio, and getting the most out of it in production means following a systematic approach to configuration, tuning, and deployment.
This comprehensive checklist covers everything you need to know before taking your hyperlane application live.
Table of Contents
- Security Configuration
- Performance Tuning
- Monitoring and Logging
- Docker Deployment
- Linux Kernel Optimization
- Build Optimization
- Server Configuration
- Error Handling in Production
- Multi-Server and Process Management
- Final Pre-Launch Checklist
Security Configuration
CORS Configuration
Cross-Origin Resource Sharing (CORS) is one of the first security settings to configure. Hyperlane provides built-in CORS middleware:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Configure CORS through middleware
// Use request_middleware to validate origins
// and response_middleware to set CORS headers
server.run().await;
}
Request Validation
Always validate incoming requests before processing them. Hyperlane's request attributes provide a clean way to extract and validate data:
#[route("/api/data")]
#[request_body_json]
#[request_header]
async fn handle_data(ctx: Context) -> Result<(), RequestError> {
let method = ctx.get_request().get_method();
let path = ctx.get_request().get_path();
let host = ctx.get_request().get_host();
// Validate request parameters
if path.is_empty() {
return Err(RequestError::new("Invalid path", 400));
}
let mut response = ctx.get_mut_response();
response.set_status_code(200);
response.set_body(r#"{"status": "ok"}"#);
Ok(())
}
Method Filtering
Restrict which HTTP methods are allowed on your endpoints:
#[route("/api/resource")]
#[methods("GET", "POST")]
async fn handle_resource(ctx: Context) -> Result<(), RequestError> {
// Only GET and POST requests reach this handler
let method = ctx.get_request().get_method();
let mut response = ctx.get_mut_response();
response.set_status_code(200);
response.set_body(format!("Method: {}", method));
Ok(())
}
Host and Referer Filtering
Use hyperlane's host and referer filtering to prevent unauthorized access:
#[route("/admin")]
#[host("admin.example.com")]
async fn admin_panel(ctx: Context) -> Result<(), RequestError> {
// Only requests to admin.example.com reach this handler
let mut response = ctx.get_mut_response();
response.set_status_code(200);
response.set_body(r#"{"panel": "admin"}"#);
Ok(())
}
Cookie Security
When using cookies, always set security flags:
use hyperlane::*;
let cookie = CookieBuilder::new("session", "encrypted-session-id")
.set_path("/")
.http_only()
.secure()
.set_max_age(3600)
.build();
The http_only() flag prevents JavaScript access, and secure() ensures the cookie is only sent over HTTPS.
Request Size Limits
Configure request size limits to prevent denial-of-service attacks:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Configure request limits
server.request_config = RequestConfig::from_json(r#"{
"max_body_size": 1048576,
"max_header_count": 100,
"max_path_size": 2048,
"read_timeout_ms": 30000
}"#).await;
server.run().await;
}
Performance Tuning
Understanding Hyperlane's Performance
Hyperlane delivers exceptional performance out of the box:
- Keep-Alive disabled: 51,031 QPS
- Keep-Alive enabled: 334,888 QPS
- ab 1 million requests: 316,211 QPS
These numbers mean that for most workloads, hyperlane's HTTP layer will not be the bottleneck.
Server Configuration for Performance
Configure the server for optimal network performance:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Set server network options
server.server_config.set_address("0.0.0.0:8080");
server.server_config.set_nodelay(true);
server.server_config.set_ttl(64);
server.run().await;
}
Setting nodelay to true disables Nagle's algorithm, reducing latency for small requests.
Connection Management
Proper connection management is critical for high-throughput scenarios:
use hyperlane::*;
#[route("/api/stream")]
async fn stream_handler(ctx: Context) -> Result<(), RequestError> {
// Check if connection is keep-alive
if stream.is_keep_alive() {
// Optimize for persistent connections
}
// Close connection when done if needed
stream.set_closed(true);
Ok(())
}
Response Optimization
Use hyperlane's response attributes for efficient response building:
#[route("/api/fast")]
#[response_status_code(200)]
#[response_header("content-type", "application/json")]
#[response_header("cache-control", "no-cache")]
async fn fast_response(ctx: Context) -> Result<(), RequestError> {
let mut response = ctx.get_mut_response();
response.set_body(r#"{"data": "fast"}"#);
Ok(())
}
Using Compression
Enable HTTP compression to reduce bandwidth usage:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Compression is configured through server config
// Enable gzip and deflate for text-based responses
server.run().await;
}
Monitoring and Logging
Structured Logging
Use the hyperlane-log crate for structured logging in production:
use hyperlane::*;
#[request_middleware(1)]
async fn logging_middleware(ctx: Context) -> Result<(), RequestError> {
let method = ctx.get_request().get_method();
let path = ctx.get_request().get_path();
let host = ctx.get_request().get_host();
// Log incoming request
log::info!("Request: {} {} from {}", method, path, host);
Ok(())
}
Error Logging
Log errors for debugging and monitoring:
#[request_error]
async fn error_logger(ctx: Context) -> Result<(), RequestError> {
if let Some(error_data) = ctx.try_get_request_error_data() {
log::error!("Request error: {}", error_data);
}
Ok(())
}
Panic Handling for Monitoring
Use #[task_panic] to catch and log panics:
#[task_panic]
async fn panic_monitor(ctx: Context) -> Result<(), RequestError> {
if let Some(panic_data) = ctx.try_get_task_panic_data() {
log::error!("Task panic detected: {:?}", panic_data);
// Send alert to monitoring system
}
Ok(())
}
Health Check Endpoint
Implement a health check endpoint for load balancers and monitoring:
#[route("/health")]
async fn health_check(ctx: Context) -> Result<(), RequestError> {
let mut response = ctx.get_mut_response();
response.set_status_code(200);
response.set_header("content-type", "application/json");
response.set_body(r#"{"status": "healthy"}"#);
Ok(())
}
Request Metrics
Track request metrics using middleware:
#[request_middleware(1)]
async fn metrics_middleware(ctx: Context) -> Result<(), RequestError> {
let start = std::time::Instant::now();
// Process request...
let duration = start.elapsed();
log::info!(
"Request to {} completed in {:?}",
ctx.get_request().get_path(),
duration
);
Ok(())
}
Docker Deployment
Development Deployment
For development environments, use the development Docker Compose configuration:
docker compose -f ./resources/docker/dev/server_docker_compose.yml up -d
Production Deployment
For production environments, use the production Docker Compose configuration:
docker compose -f ./resources/docker/release/server_docker_compose.yml up -d
Multi-Server Deployment with Docker
Deploy multiple hyperlane instances behind a load balancer:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Format bind address for Docker networking
let bind_address = Server::format_bind_address("0.0.0.0", 8080);
server.server_config.set_address(&bind_address);
server.run().await;
}
Docker Health Checks
Configure health checks in your Docker Compose file to ensure container reliability:
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8080/health']
interval: 30s
timeout: 10s
retries: 3
Linux Kernel Optimization
TCP Connection Tuning
For high-concurrency deployments, tune the Linux kernel TCP parameters:
# Increase TIME_WAIT bucket size
net.ipv4.tcp_max_tw_buckets = 20000
# Increase the maximum number of pending connections
net.core.somaxconn = 65535
# Increase the maximum number of SYN backlog
net.ipv4.tcp_max_syn_backlog = 262144
File Descriptor Limits
Increase the file descriptor limit to handle many concurrent connections:
ulimit -n 1024000
Applying Kernel Settings
Add these settings to /etc/sysctl.conf for persistence across reboots:
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_max_tw_buckets = 20000
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 262144
EOF
sysctl -p
Build Optimization
Native CPU Targeting
Compile with native CPU targeting for maximum performance:
RUSTFLAGS="-C target-cpu=native -C link-arg=-fuse-ld=lld" cargo run --release
The -C target-cpu=native flag enables CPU-specific optimizations, and -C link-arg=-fuse-ld=lld uses the faster LLD linker.
Release Builds
Always use release builds for production:
cargo build --release
Release builds enable optimizations that significantly improve performance at the cost of longer compile times.
Profile Configuration
Configure your Cargo.toml for optimal release builds:
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true
Server Configuration
Address and Port Configuration
Configure the server to bind to the correct address and port:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
server.server_config.set_address("0.0.0.0:8080");
server.run().await;
}
Request Configuration
Fine-tune request handling parameters:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
server.request_config = RequestConfig::from_json(r#"{
"buffer_size": 8192,
"max_path_size": 2048,
"max_header_count": 100,
"max_body_size": 1048576,
"read_timeout_ms": 30000
}"#).await;
server.run().await;
}
Configuration from JSON
Load server configuration from a JSON file for easy environment-specific settings:
use hyperlane::*;
#[tokio::main]
async fn main() {
let config = config_from_json("config.json").await;
let server = Server::default();
// Apply configuration
server.run().await;
}
Network Options
Configure TCP network options for optimal performance:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Disable Nagle's algorithm for lower latency
server.server_config.set_nodelay(true);
// Set TTL for network packets
server.server_config.set_ttl(64);
server.run().await;
}
Error Handling in Production
Graceful Error Handling
Implement comprehensive error handling for production:
#[request_error]
async fn production_error_handler(ctx: Context) -> Result<(), RequestError> {
if let Some(error_data) = ctx.try_get_request_error_data() {
log::error!("Request error occurred: {}", error_data);
let mut response = ctx.get_mut_response();
response.set_status_code(500);
response.set_header("content-type", "application/json");
response.set_body(r#"{"error": "Internal server error"}"#);
}
Ok(())
}
Panic Recovery
Handle task panics gracefully:
#[task_panic]
async fn production_panic_handler(ctx: Context) -> Result<(), RequestError> {
if let Some(panic_data) = ctx.try_get_task_panic_data() {
log::error!("Task panic: {:?}", panic_data);
// Alert monitoring system
}
Ok(())
}
Graceful Shutdown
Implement graceful shutdown to handle in-flight requests:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server = Server::default();
// Setup server...
// Run server with graceful shutdown
server.control_hook.wait().await;
server.control_hook.shutdown().await;
}
Multi-Server and Process Management
Running Multiple Servers
Use tokio::spawn to run multiple hyperlane instances:
use hyperlane::*;
#[tokio::main]
async fn main() {
let server1 = Server::default();
server1.server_config.set_address("0.0.0.0:8080");
let server2 = Server::default();
server2.server_config.set_address("0.0.0.0:8081");
let handle1 = tokio::spawn(async move {
server1.run().await;
});
let handle2 = tokio::spawn(async move {
server2.run().await;
});
tokio::join!(handle1, handle2);
}
Format Bind Address
Use the built-in helper for consistent address formatting:
use hyperlane::*;
let addr = Server::format_bind_address("0.0.0.0", 8080);
Final Pre-Launch Checklist
Before deploying to production, verify the following:
Security
- [ ] CORS properly configured
- [ ] Request size limits set (
max_body_size,max_header_count,max_path_size) - [ ] HTTP method filtering applied on all endpoints
- [ ] Host/referer filtering configured where needed
- [ ] Cookie security flags set (
http_only,secure) - [ ] HTTPS/TLS configured (via reverse proxy like nginx)
Performance
- [ ] Keep-Alive enabled for high-throughput scenarios
- [ ]
nodelayset totruefor low-latency responses - [ ] HTTP compression enabled
- [ ] Connection pool sizes tuned for database backends
- [ ] Linux kernel parameters optimized
- [ ] Build compiled with
RUSTFLAGS="-C target-cpu=native -C link-arg=-fuse-ld=lld"and--release
Monitoring
- [ ] Structured logging configured via
hyperlane-log - [ ] Error handling middleware active (
#[request_error]) - [ ] Panic handling middleware active (
#[task_panic]) - [ ] Health check endpoint implemented at
/health - [ ] Request metrics being collected
Deployment
- [ ] Docker Compose configuration selected (dev vs. release)
- [ ] Graceful shutdown implemented
- [ ] Multi-server setup configured if needed
- [ ] Load balancer configured in front of hyperlane instances
- [ ] File descriptor limits increased (
ulimit -n 1024000)
Infrastructure
- [ ] Server address and port configured correctly
- [ ] Request timeout values set appropriately
- [ ] Configuration loaded from JSON for environment-specific settings
Conclusion
Deploying hyperlane to production requires attention to security, performance, monitoring, and infrastructure. By following this checklist, you can ensure that your hyperlane application is ready for the demands of production traffic.
Remember that hyperlane already provides exceptional performance — up to 334,888 QPS with Keep-Alive enabled — so the key to a successful production deployment lies in proper configuration, monitoring, and infrastructure setup rather than HTTP layer optimization.
Leverage the hyperlane ecosystem tools like hyperlane-log for logging, hyperlane-utils for utilities, server-manager for lifecycle management, and utoipa for API documentation to build a complete production-ready application.
Project Code:https://github.com/hyperlane-dev/hyperlane
Top comments (0)