Hermes Deep Dive: The Developer’s Guide - 2026-07-24
Published: July 24, 2026 | Reading time: 12 minutes
What is Hermes?
Origin and Background
Hermes emerged from the trenches of modern microservice architecture hell. Created by a team of ex-Uber engineers in late 2024, Hermes was designed to solve a problem that had been plaguing distributed systems for years: inter-service communication that’s both fast and reliable without the operational overhead of traditional message brokers.
The project’s name is fitting—Hermes, the Greek messenger god, represents the tool’s core mission: delivering messages between services with divine speed and reliability. Version 1.0.0 dropped in March 2025, and by July 2026, Hermes has become the de facto standard for lightweight service mesh communication, with over 2.3 million monthly Docker pulls and adoption at companies like Stripe, Figma, and Datadog.
Core Value Proposition
Hermes is an in-process message broker and service mesh proxy that eliminates the need for external message queues (RabbitMQ, Kafka) or sidecar proxies (Envoy, Linkerd) in most microservice architectures. It runs as a library embedded directly into your application process, providing:
- Sub-millisecond message delivery (0.3ms p50, 2.1ms p99 in production benchmarks)
- Zero infrastructure dependencies (no ZooKeeper, no etcd, no Kafka clusters)
- Automatic service discovery via DNS-based peer resolution
- Built-in circuit breaking, retries, and rate limiting
- Native gRPC, HTTP/2, and WebSocket support
What Makes It Different
Unlike traditional message brokers that require dedicated infrastructure, or sidecar proxies that double your resource consumption, Hermes operates at the application layer with minimal overhead. The killer feature? Hermes uses UDP-based multicast for local service discovery and TCP for actual message delivery, achieving 40% lower latency than Envoy in identical workloads while using 60% less memory.
🚀 Getting Started
Installation
Hermes supports Go, Rust, Node.js, and Python. We’ll focus on the Go implementation, which is the most mature and performant.
# Install the Hermes CLI tool
go install github.com/hermes-io/[email protected]
# Verify installation
hermes version
# Output: Hermes CLI v1.8.3 (build 2026-07-22)
# Initialize a new Hermes project
hermes init my-service
cd my-service
# Install the Go library
go get github.com/hermes-io/[email protected]
For Docker-based deployments, the official image is available:
docker pull hermesio/hermes:1.8.3-alpine
Configuration
Hermes uses a YAML configuration file that can be generated automatically or written manually. Here’s a minimal configuration:
# hermes.yaml
service:
name: "order-service"
port: 8080
version: "1.0.0"
discovery:
mode: "dns" # Options: dns, kubernetes, consul, static
domain: "services.internal"
refresh_interval: 30s
messaging:
transport: "tcp"
compression: "snappy"
max_message_size: 10MB
circuit_breaker:
enabled: true
failure_threshold: 5
recovery_timeout: 30s
rate_limiting:
enabled: true
requests_per_second: 1000
burst: 100
Generate the configuration automatically:
hermes config init --service order-service --port 8080 --discovery dns
This creates a hermes.yaml file that you can customize further.
💡 Core Features
Feature 1: Automatic Service Discovery
Description: Hermes eliminates the need for manual service registration or external service discovery tools. It uses DNS-based discovery with automatic health checking and load balancing.
Usage Example:
package main
import (
"context"
"log"
"time"
"github.com/hermes-io/hermes-go"
)
func main() {
// Initialize Hermes client
client, err := hermes.NewClient(hermes.Config{
ServiceName: "payment-service",
Port: 9090,
Discovery: hermes.DiscoveryConfig{
Mode: "dns",
Domain: "services.internal",
},
})
if err != nil {
log.Fatal(err)
}
// Discover and call the "inventory-service" endpoint
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Hermes automatically resolves the service and load balances
response, err := client.Call(ctx, "inventory-service", hermes.Request{
Method: "GET",
Path: "/api/v1/stock/check",
Body: []byte(`{"product_id": "PROD-123", "quantity": 5}`),
})
if err != nil {
log.Printf("Failed to call inventory service: %v", err)
return
}
log.Printf("Inventory response: %s", response.Body)
}
Real-world application: At Figma, Hermes handles 50,000+ service-to-service calls per second across their collaborative editing infrastructure. The DNS-based discovery reduced their service mesh configuration complexity by 80% compared to their previous Envoy-based setup.
Feature 2: Intelligent Circuit Breaking
Description: Hermes implements a sophisticated circuit breaker pattern that prevents cascading failures in distributed systems. It monitors failure rates, response times, and error types to make intelligent decisions about when to open, half-open, or close circuits.
Usage Example:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/hermes-io/hermes-go"
)
func main() {
client, _ := hermes.NewClient(hermes.Config{
ServiceName: "api-gateway",
Port: 8080,
CircuitBreaker: hermes.CircuitBreakerConfig{
Enabled: true,
FailureThreshold: 3, // Open after 3 consecutive failures
RecoveryTimeout: 30 * time.Second, // Wait 30s before half-open
HalfOpenMaxCalls: 2, // Allow 2 test calls in half-open state
SuccessThreshold: 2, // Close after 2 successful test calls
},
})
// Simulate a call to an unreliable service
for i := 0; i < 10; i++ {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
response, err := client.Call(ctx, "unreliable-service", hermes.Request{
Method: "GET",
Path: "/api/health",
})
if err != nil {
fmt.Printf("Call %d failed: %v\n", i+1, err)
if hermes.IsCircuitBreakerError(err) {
fmt.Printf(" → Circuit is OPEN, skipping request\n")
}
} else {
fmt.Printf("Call %d succeeded: %s\n", i+1, response.Body)
}
cancel()
time.Sleep(500 * time.Millisecond)
}
}
Real-world application: Stripe uses Hermes’s circuit breaker in their payment processing pipeline. When a downstream payment gateway experiences issues, Hermes automatically opens the circuit after 3 failures, preventing a flood of failed requests that would overwhelm the gateway and degrade the entire system. This reduced their P99 latency spikes by 94% during partial outages.
Feature 3: Request-Response Streaming with Backpressure
Description: Hermes supports bidirectional streaming with automatic backpressure handling. This is crucial for real-time applications where you need to process large datasets or continuous data streams without overwhelming either the producer or consumer.
Usage Example:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/hermes-io/hermes-go/stream"
)
func main() {
// Create a streaming client
client, _ := hermes.NewStreamClient(hermes.Config{
ServiceName: "data-processor",
Port: 7070,
Stream: hermes.StreamConfig{
MaxConcurrentStreams: 100,
WindowSize: 64 * 1024, // 64KB flow control window
Backpressure: hermes.BackpressureConfig{
Strategy: "window", // Options: window, rate, hybrid
MaxBufferedMessages: 1000,
DropPolicy: "oldest", // Drop oldest messages when buffer full
},
},
})
// Establish a stream to the "log-aggregator" service
stream, err := client.Stream(context.Background(), "log-aggregator", "/api/v1/logs/stream")
if err != nil {
log.Fatal(err)
}
defer stream.Close()
// Send 10,000 log entries with backpressure handling
for i := 0; i < 10000; i++ {
message := fmt.Sprintf(`{"timestamp": %d, "level": "INFO", "message": "Event #%d"}`,
time.Now().Unix(), i)
err := stream.Send([]byte(message))
if err != nil {
if hermes.IsBackpressureError(err) {
log.Printf("Backpressure applied, retrying in 100ms...")
time.Sleep(100 * time.Millisecond)
// Retry the send
err = stream.Send([]byte(message))
if err != nil {
log.Printf("Failed to send after backpressure: %v", err)
}
} else {
log.Printf("Stream error: %v", err)
}
}
// Simulate production rate of 1000 messages/second
time.Sleep(1 * time.Millisecond)
}
// Receive responses
for response := range stream.Receive() {
fmt.Printf("Received: %s\n", response.Body)
}
}
Real-world application: Datadog uses Hermes’s streaming capabilities to process 2.5 million log entries per second across their ingestion pipeline. The backpressure mechanism ensures that when a downstream processing service slows down, Hermes automatically throttles the producer, preventing OOM crashes that were common with their previous Kafka-based setup.
🛠️ Advanced Workflows
Workflow 1: Multi-Service Orchestration with Saga Pattern
This workflow demonstrates how to implement a distributed transaction using the Saga pattern with Hermes’s built-in compensation mechanism.
# Initialize three services
hermes init order-service --port 8080
hermes init payment-service --port 8081
hermes init inventory-service --port 8082
# Configure service dependencies
cat > order-service/hermes.yaml << EOF
service:
name: "order-service"
port: 8080
saga:
enabled: true
timeout: 30s
compensation:
retry_count: 3
retry_delay: 1s
EOF
# Start all services with Hermes
hermes start order-service &
hermes start payment-service &
hermes start inventory-service &
# Deploy the saga workflow
cat > order-service/saga.yaml << EOF
saga:
name: "create-order"
steps:
- service: "inventory-service"
action: "reserve-inventory"
compensation: "release-inventory"
timeout: 5s
- service: "payment-service"
action: "charge-customer"
compensation: "refund-customer"
timeout: 10s
- service: "inventory-service"
action: "confirm-reservation"
compensation: "cancel-order"
timeout: 5s
EOF
# Execute the saga
hermes saga execute order-service create-order \
--data '{"order_id": "ORD-123", "customer_id": "CUST-456", "amount": 99.99}'
This workflow ensures that if the payment step fails, the inventory reservation is automatically released, maintaining data consistency across services.
Workflow 2: Real-Time Metrics Aggregation with Hermes Streams
This workflow shows how to build a real-time metrics pipeline that aggregates data from multiple services.
# Create a metrics aggregator service
hermes init metrics-aggregator --port 9090
# Configure stream aggregation
cat > metrics-aggregator/hermes.yaml << EOF
service:
name: "metrics-aggregator"
port: 9090
stream:
enabled: true
aggregation:
window_size: 60s
sliding_window: true
metrics:
- name: "request_latency_p50"
type: "percentile"
value: 50
- name: "request_latency_p99"
type: "percentile"
value: 99
- name: "error_rate"
type: "rate"
unit: "per_second"
- name: "throughput"
type: "counter"
unit: "requests"
EOF
# Start the aggregator
hermes start metrics-aggregator &
# Configure each service to emit metrics
for service in order-service payment-service inventory-service; do
cat >> $service/hermes.yaml << EOF
metrics:
enabled: true
stream_to: "metrics-aggregator"
interval: 10s
include:
- request_latency
- error_count
- request_count
EOF
done
# Restart services with metrics enabled
hermes restart order-service payment-service inventory-service
# Query aggregated metrics
hermes metrics query --service metrics-aggregator --window 5m --metric request_latency_p99
# Output: request_latency_p99: 245ms (5-minute window, sliding)
This setup provides real-time visibility into service health without the overhead of a separate monitoring infrastructure.
📊 Comparison with Alternatives
| Feature | Hermes | RabbitMQ | Apache Kafka | Envoy |
|---|---|---|---|---|
| In-process deployment | ✅ Yes | ❌ External broker | ❌ External cluster | ❌ Sidecar proxy |
| P99 latency (local) | 2.1ms | 15ms | 25ms | 5.3ms |
| Memory per instance | 45MB | 256MB | 1.2GB | 128MB |
| Service discovery | ✅ Built-in | ❌ Requires external | ❌ Requires ZK | ✅ Built-in |
| Circuit breaking | ✅ Built-in | ❌ Manual impl. | ❌ Manual impl. | ✅ Built-in |
| Streaming with backpressure | ✅ Native | ✅ Good | ✅ Excellent | ❌ Limited |
| Saga transactions | ✅ Built-in | ❌ No | ❌ No | ❌ No |
| gRPC support | ✅ Native | ❌ HTTP only | ❌ HTTP only | ✅ Native |
| WebSocket support | ✅ Native | ❌ Requires plugin | ❌ Requires plugin | ✅ Native |
| Configuration complexity | Low | Medium | High | High |
| Learning curve | Low | Medium | High | Medium |
| Production readiness | ✅ GA v1.8.3 | ✅ Mature | ✅ Mature | ✅ Mature |
🎯 Pro Tips
1. Optimize for Local Development with Hermes Dev Mode
# Enable dev mode for hot-reloading and detailed logging
export HERMES_DEV=true
hermes start order-service
# Dev mode features:
# - Automatic recompilation on file changes
# - Structured JSON logging to stdout
# - Mock service responses for testing
# - Performance profiling endpoints at /debug/hermes
Dev mode reduces your development feedback loop from minutes to seconds. The HERMES_DEV=true flag enables a built-in file watcher that automatically restarts services when source code changes.
2. Use Hermes’s Built-in Distributed Tracing
# Enable OpenTelemetry integration
cat >> hermes.yaml << EOF
tracing:
enabled: true
exporter: "otlp"
endpoint: "otel-collector:4317"
sample_rate: 0.1 # Sample 10% of requests in production
EOF
# View traces in real-time
hermes traces --service order-service --last 5m
Hermes automatically propagates trace context across service boundaries without any code changes. This gives you end-to-end visibility into request flows with zero instrumentation overhead.
3. Implement Graceful Degradation with Feature Flags
# Define feature flags in Hermes config
cat >> hermes.yaml << EOF
feature_flags:
- name: "new-payment-flow"
enabled: true
rollout_percentage: 25
fallback_service: "payment-service-legacy"
EOF
# Check feature flag at runtime
hermes feature-flag check new-payment-flow
# Returns: true (25% of requests)
Use Hermes’s built-in feature flag system to gradually roll out new service versions. If the new service fails, Hermes automatically falls back to the legacy service, ensuring zero downtime during deployments.
🔗 Resources
Official Documentation
- Hermes Documentation: https://docs.hermes.io - Complete API reference, tutorials, and best practices
- GitHub Repository: https://github.com/hermes-io/hermes - Source code, issues, and contributions
- Release Notes: https://github.com/hermes-io/hermes/releases - Changelog for all versions
Community
- Discord Server: https://discord.gg/hermes-io - 12,000+ active members, real-time support
- Stack Overflow: Tag your questions with
hermes-iofor community answers - Monthly Meetups: Every first Wednesday, virtual and in-person events
Related Tools
- Hermes Dashboard: https://dashboard.hermes.io - Visual monitoring and management UI
- Hermes CLI Extensions: https://github.com/hermes-io/hermes-cli-plugins - Community plugins for Kubernetes, AWS, and GCP
- Hermes Benchmark Suite: https://github.com/hermes-io/hermes-bench - Performance testing tools for your specific workloads
Learning Path
- Beginner: Complete the official “Hermes in 10 Minutes” tutorial
- Intermediate: Build a multi-service application with Saga transactions
- Advanced: Implement custom middleware and plugins for Hermes
Hermes v1.8.3 is available now. The project is actively maintained with weekly releases and a vibrant community. Whether you’re building a startup’s first microservice or scaling a Fortune 500’s infrastructure, Hermes provides the performance and simplicity modern developers demand.
Have questions? Join the Discord community or open an issue on GitHub. Happy messaging! 🚀
Have questions? Join our Discord community or follow us on X.