A complete example demonstrating how to build an event-driven application using redis-messaging.
This sample shows how to publish messages, consume them asynchronously, validate incoming data, retry failed processing, persist data into MySQL, and expose health endpoints suitable for Kubernetes and cloud-native deployments.
Rather than being a simple Redis Pub/Sub example, this project demonstrates how redis-messaging integrates with the core-ts ecosystem to build production-ready services.
HTTP Request
│
▼
REST Endpoint
│
▼
RedisPublisher<User>
│
▼
Redis Pub/Sub
│
▼
RedisSubscriber<User>
│
▼
Processor
│
┌───────────┴───────────┐
▼ ▼
Validation Retry Handler
│
▼
MySQL Writer
│
▼
MySQL
- Publish messages to Redis Pub/Sub
- Consume messages asynchronously
- Strongly typed message processing
- Message validation
- Automatic retry handling
- MySQL persistence
- Health check endpoint
- Dependency Injection
- Structured logging
- Configuration management
- TypeScript
- Node.js
- Redis
- MySQL
- redis-messaging
- mysql2-core
- validation-core
- message-processing
- config-plus
- health-service
src
├── config.ts
├── context.ts
├── index.ts
└── user
└── index.ts
- Node.js 18+
- Redis 6+
- MySQL 8+
Clone the project.
git clone https://github.com/core-ts/redis-messaging-sample.gitInstall dependencies.
npm installUpdate the application configuration.
export const config = {
redis: {
url: "redis://localhost:6379",
},
mysql: {
host: "localhost",
port: 3306,
database: "sample",
user: "root",
password: "password",
},
}Example using Docker.
docker run \
-d \
--name redis \
-p 6379:6379 \
redis:latestExample using Docker.
docker run \
-d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=sample \
-p 3306:3306 \
mysql:8npm run devor
npm startSend an HTTP request.
POST /send
Content-Type: application/jsonExample body
{
"id": "1001",
"name": "John",
"email": "john@example.com"
}The application will
- Receive the HTTP request
- Publish the message to Redis
- Redis broadcasts the message
- Subscriber receives the message
- Validate the payload
- Retry on transient failures
- Save the data into MySQL
GET /health
The endpoint checks:
- Redis connectivity
- MySQL connectivity
They can easily be extended to include additional infrastructure services.
Example response
{
"status": "UP",
"details": {
"redis": {
"status": "UP"
},
"mysql": {
"status": "UP"
}
}
}This endpoint is suitable for Kubernetes liveness and readiness probes.
HTTP Client
│
▼
PublishController
│
▼
RedisPublisher
│
▼
Redis Server
│
▼
RedisSubscriber
│
▼
Processor
│
▼
Validator
│
▼
RetryWriter
│
▼
MySQLWriter
│
▼
MySQL
The sample demonstrates retry processing for transient failures.
Attempt 1
│
▼
Failed
│
▼
Wait
│
▼
Attempt 2
│
▼
Failed
│
▼
Wait
│
▼
Attempt 3
This approach helps improve reliability when temporary database or network issues occur.
Messages are validated by validation-core before reaching business logic.
Typical validation includes
- Required fields
- String length
- Email format
- Business constraints
Invalid messages are rejected before reaching the database.
Redis Pubsub
↓
Processor
↓
Validator
↓
Business Logic
This project demonstrates much more than Redis Pub/Sub.
It shows how to build a production-style event-driven service using small, reusable libraries.
Highlights include:
- Clean separation of concerns
- Dependency Injection
- Event-driven architecture
- Type-safe messaging
- Validation
- Retry handling
- Health monitoring
- Database persistence
The createContext() function acts as a composition root.
It wires together:
- Redis Pubsub
- Health service
- Validation
- MySQL
- Retry
- Logging
- Processor
without mixing business logic.
That's exactly where dependency injection should happen.
This sample demonstrates how several core-ts libraries work together.
| Library | Purpose |
|---|---|
redis-messaging |
Publish and subscribe to Redis |
message-processing |
Retry and error handling |
mysql2-core |
Write data into MySQL |
validation-core |
Validate incoming messages |
health-service |
Health endpoint |
logger-core |
Structured logging |
config-plus |
Configuration management |
Each library focuses on a single responsibility.
That demonstrates the intended layering very well.
One of the goals of this sample is to demonstrate proper layering.
Responsible for:
- Producer
- Consumer
- Header mapping
- Health checking
Responsible for:
- JSON deserialization
- Validation
- Processing pipeline
- Retry
- Error handling
- Logging
Responsible only for business logic.
Process Order
Save Customer
Import Product
Send Notification
Business services remain independent of NATS.
Instead of embedding business logic inside RabbitMQ consumers,
Consumer
↓
Business Logic
↓
Database
↓
Retry
↓
Validation
the sample separates every concern.
Consumer
↓
Processor
↓
Validation
↓
Retry
↓
Business Logic
↓
Writer
Each layer has a single responsibility.
This makes the application:
- easier to maintain
- easier to test
- easier to replace infrastructure
- easier to extend
This sample demonstrates production-oriented practices including:
- Layered architecture
- Strong typing
- Validation
- Retry processing
- Logging
- Health monitoring
- Infrastructure abstraction
Additional production features such as dead-letter queues, delayed retry queues, metrics, and distributed tracing can be added without changing the application architecture.
MIT