Transport Comparison¶
SmartMessage provides multiple transport layers, each designed for different use cases and requirements. This document provides a comprehensive comparison to help you choose the right transport for your application.
Transport Overview¶
Transport | Type | Best For | Key Feature |
---|---|---|---|
Memory | In-Memory Queue | Testing, development | No external dependencies, fast |
STDOUT | Logging/Debug | Development, debugging | Human-readable output |
Redis | Pub/Sub | Production messaging | Distributed, persistent connections |
🧠 Memory Transport¶
Perfect for development, testing, and in-memory message queuing.
Architecture¶
Key Characteristics¶
- Message Persistence: In-memory only - lost on restart
- Pattern Support: None - direct message class routing
- Load Balancing: No - all subscribers receive all messages
- Threading: Thread-safe with mutex protection
- External Dependencies: None
Configuration¶
SmartMessage::Transport.create(:memory,
auto_process: true, # Automatically route messages to dispatcher
max_messages: 1000 # Maximum messages to store in memory
)
Use Cases¶
- Unit testing - Predictable, isolated environment
- Development - Quick setup without external services
- In-memory queuing - Fast processing without persistence
- Message inspection - Easy access to all stored messages
Pros¶
- ✅ No external dependencies
- ✅ Fastest performance (no serialization)
- ✅ Thread-safe operations
- ✅ Message inspection capabilities
- ✅ Memory overflow protection
Cons¶
- ❌ Messages lost on restart
- ❌ Single-process only
- ❌ Memory usage grows with message volume
- ❌ No network distribution
Example¶
class TestMessage < SmartMessage::Base
property :data
config do
transport SmartMessage::Transport.create(:memory, auto_process: true)
end
def self.process(decoded_message)
puts "Processing: #{decoded_message.data}"
end
end
TestMessage.subscribe
TestMessage.new(data: "Hello World").publish
📄 STDOUT Transport¶
Ideal for development, debugging, and logging scenarios.
Architecture¶
Publisher → Console/File Output → Optional Loopback → Subscriber
(JSON formatting) (if enabled) (local processing)
Key Characteristics¶
- Message Persistence: File-based if output specified
- Pattern Support: None - logging/debugging focused
- Load Balancing: No - single output destination
- Threading: Thread-safe file operations
- External Dependencies: None
Configuration¶
SmartMessage::Transport.create(:stdout,
loopback: true, # Process messages locally
output: "messages.log" # Output to file instead of console
)
Use Cases¶
- Development debugging - See messages in real-time
- Application logging - Structured message logging
- Message tracing - Track message flow through system
- Integration testing - Verify message content
Pros¶
- ✅ Human-readable JSON output
- ✅ File-based persistence option
- ✅ Optional loopback for testing
- ✅ No external dependencies
- ✅ Structured message formatting
Cons¶
- ❌ Not suitable for production messaging
- ❌ Single output destination
- ❌ No network distribution
- ❌ Limited throughput for high-volume scenarios
Example¶
class LogMessage < SmartMessage::Base
property :level
property :message
property :timestamp, default: -> { Time.now.iso8601 }
config do
transport SmartMessage::Transport.create(:stdout,
output: "app.log",
loopback: false
)
end
end
LogMessage.new(level: "INFO", message: "Application started").publish
🔴 Redis Transport¶
Production-ready Redis pub/sub transport for distributed messaging.
Architecture¶
Key Characteristics¶
- Message Persistence: No - fire-and-forget pub/sub
- Pattern Support: None - exact channel name matching
- Load Balancing: No - all subscribers receive all messages
- Threading: Traditional thread-per-subscriber model
- External Dependencies: Redis server
Configuration¶
SmartMessage::Transport.create(:redis,
url: 'redis://localhost:6379', # Redis connection URL
db: 0, # Redis database number
auto_subscribe: true, # Automatically start subscriber
reconnect_attempts: 5, # Connection retry attempts
reconnect_delay: 1 # Delay between retries (seconds)
)
Use Cases¶
- Production messaging - Reliable distributed messaging
- Microservices communication - Service-to-service messaging
- Real-time applications - Low-latency message delivery
- Scalable architectures - Multiple publishers and subscribers
Pros¶
- ✅ Production-ready reliability
- ✅ Distributed messaging support
- ✅ Automatic reconnection handling
- ✅ Low latency (~1ms)
- ✅ High throughput (80K+ messages/second)
- ✅ Automatic serialization (MessagePack/JSON)
Cons¶
- ❌ Requires Redis server
- ❌ No message persistence
- ❌ No pattern-based routing
- ❌ No load balancing
- ❌ All subscribers receive all messages
Example¶
class OrderMessage < SmartMessage::Base
property :order_id
property :customer_id
property :amount
config do
transport SmartMessage::Transport.create(:redis,
url: ENV['REDIS_URL'] || 'redis://localhost:6379',
db: 1
)
end
def self.process(decoded_message)
order = decoded_message
puts "Processing order #{order.order_id} for $#{order.amount}"
end
end
OrderMessage.subscribe
OrderMessage.new(
order_id: "ORD-123",
customer_id: "CUST-456",
amount: 99.99
).publish
📊 Feature Comparison Matrix¶
Feature | Memory | STDOUT | Redis |
---|---|---|---|
Message Persistence | ❌ Memory Only | ✅ File Optional | ❌ No |
Network Distribution | ❌ No | ❌ No | ✅ Yes |
External Dependencies | ❌ None | ❌ None | ✅ Redis |
Pattern Matching | ❌ No | ❌ No | ❌ No |
Load Balancing | ❌ No | ❌ No | ❌ No |
Setup Complexity | Easy | Easy | Medium |
Performance (Latency) | ~0.1ms | ~1ms | ~1ms |
Performance (Throughput) | Highest | Medium | High |
Serialization | None | JSON | MessagePack/JSON |
Thread Safety | ✅ Yes | ✅ Yes | ✅ Yes |
Message Inspection | ✅ Yes | ✅ Yes | ❌ No |
Production Ready | ❌ Testing Only | ❌ Logging Only | ✅ Yes |
Horizontal Scaling | ❌ No | ❌ No | ✅ Yes |
🎯 Choosing the Right Transport¶
Use Memory Transport When:¶
- ✅ You're writing unit tests
- ✅ You're developing locally
- ✅ You need fast, in-memory message processing
- ✅ You want to inspect messages for testing
- ✅ You don't need persistence or distribution
Use STDOUT Transport When:¶
- ✅ You're debugging message flow
- ✅ You need human-readable message logging
- ✅ You're building development tools
- ✅ You want to trace messages in integration tests
- ✅ You need simple file-based message storage
Use Redis Transport When:¶
- ✅ You're building production applications
- ✅ You need distributed messaging
- ✅ You have microservices that need to communicate
- ✅ You need reliable, scalable messaging
- ✅ You can manage a Redis server dependency
🔄 Migration Patterns¶
Development → Production¶
# Development (Memory)
class MyMessage < SmartMessage::Base
config do
transport SmartMessage::Transport.create(:memory, auto_process: true)
end
end
# Production (Redis)
class MyMessage < SmartMessage::Base
config do
transport SmartMessage::Transport.create(:redis,
url: ENV['REDIS_URL'] || 'redis://localhost:6379'
)
end
end
Environment-Based Configuration¶
class MyMessage < SmartMessage::Base
config do
transport case Rails.env
when 'test'
SmartMessage::Transport.create(:memory, auto_process: true)
when 'development'
SmartMessage::Transport.create(:stdout, loopback: true)
when 'production'
SmartMessage::Transport.create(:redis, url: ENV['REDIS_URL'])
end
end
end
📈 Performance Characteristics¶
Latency Comparison¶
- Memory: ~0.1ms (fastest, no serialization)
- STDOUT: ~1ms (JSON formatting overhead)
- Redis: ~1ms (network + serialization)
Throughput Comparison¶
- Memory: Highest (limited by CPU and memory)
- STDOUT: Medium (limited by I/O operations)
- Redis: High (limited by network and Redis performance)
Memory Usage¶
- Memory: Grows with message volume (configurable limit)
- STDOUT: Minimal (immediate output/write)
- Redis: Low (messages not stored locally)
🛠️ Configuration Examples¶
Test Environment¶
SmartMessage.configure do |config|
config.default_transport = SmartMessage::Transport.create(:memory,
auto_process: true,
max_messages: 100
)
end
Development Environment¶
SmartMessage.configure do |config|
config.default_transport = SmartMessage::Transport.create(:stdout,
loopback: true,
output: "log/messages.log"
)
end
Production Environment¶
SmartMessage.configure do |config|
config.default_transport = SmartMessage::Transport.create(:redis,
url: ENV['REDIS_URL'],
db: ENV['REDIS_DB']&.to_i || 0,
reconnect_attempts: 10,
reconnect_delay: 2
)
end
This comparison should help you choose the right transport for your specific use case within the SmartMessage ecosystem. Each transport is optimized for different scenarios and provides the flexibility to grow your application from development to production.