DEV Community

tengxgfyrz67s
tengxgfyrz67s

Posted on

Production-Deployment-Checklist

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

  1. Security Configuration
  2. Performance Tuning
  3. Monitoring and Logging
  4. Docker Deployment
  5. Linux Kernel Optimization
  6. Build Optimization
  7. Server Configuration
  8. Error Handling in Production
  9. Multi-Server and Process Management
  10. 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;
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Production Deployment

For production environments, use the production Docker Compose configuration:

docker compose -f ./resources/docker/release/server_docker_compose.yml up -d
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

File Descriptor Limits

Increase the file descriptor limit to handle many concurrent connections:

ulimit -n 1024000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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(())
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
  • [ ] nodelay set to true for 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)