A distributed job scheduling system built on .NET 10
Milvaion is a distributed job scheduling system that separates the scheduler (API that decides when jobs run) from the workers (processes that execute jobs), connected via Redis and RabbitMQ.
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Milvaion API β β RabbitMQ β β Workers β
β (Scheduler) ββββββββ>β (Job Queue) βββββββ>β (Executors) β
β β β β β β
β β’ REST API β β β’ Job messages β β β’ IJob classes β
β β’ Dashboard β β β’ Status queues β β β’ Retry logic β
β β’ Cron parsing β<ββββββββ β’ Log streams β<βββββββ β’ DI support β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
Most job schedulers run jobs inside the same process as the scheduling logic. This works fine until:
- A long-running job blocks other jobs from executing
- A crashing job takes down the entire scheduler
- You need different hardware for different job types (e.g., GPU for ML jobs)
- You want to scale job execution independently from the API
Milvaion solves these problems by completely separating scheduling from execution.
- At-least-once delivery via RabbitMQ manual ACK
- Automatic retries with exponential backoff
- Dead Letter Queue for failed jobs after max retries
- Zombie detection recovers stuck jobs
- Auto disable always failing jobs (configurable threshold)
- Horizontal worker scaling - add more workers for more throughput
- Job-type routing - route specific jobs to specialized workers
- Independent scaling - scale API and workers separately
- Real-time dashboard with SignalR updates
- Execution logs - User-friendly logs stored in occurrences + technical logs to Seq
- Worker health monitoring via heartbeats
- OpenTelemetry support for metrics and tracing
- Simple
IJobinterfaces - implement one method - Full DI support - inject services into jobs
- Auto-discovery - jobs registered automatically
- Cancellation support - graceful shutdown
- Project templates - get started quickly with
dotnet new
- HTTP Worker - Call REST APIs on schedule
- SQL Worker - Execute database queries
- Email Worker - Send emails via SMTP
- Maintenance Worker - Milvaion self data warehouse cleanup and archival
- Docker Desktop (v20.10+) with Docker Compose
- Web browser for the dashboard
# Clone the repository
git clone https://github.com/Milvasoft/milvaion.git
cd milvaion
# Start all services
docker compose up -dOpen http://localhost:5000 in your browser.
- Default username:
rootuser - Get password:
docker logs milvaion-api 2>&1 | grep -i "password"
curl -X POST http://localhost:5000/api/v1/jobs/job \
-H "Content-Type: application/json" \
-d '{
"displayName": "My First Job",
"workerId": "sample-worker-01",
"selectedJobName": "SampleJob",
"cronExpression": "* * * * *",
"isActive": true,
"jobData": "{\"message\": \"Hello from Milvaion!\"}"
}'π Full Quick Start Guide β
Milvaion follows Onion Architecture principles with clear separation of concerns:
milvaion/
βββ src/
β βββ Core/
β β βββ Milvaion.Domain/ # Entities, enums, domain logic
β β βββ Milvaion.Application/ # Use cases, DTOs, interfaces
β βββ Infrastructure/
β β βββ Milvaion.Infrastructure/ # EF Core, external services
β βββ Presentation/
β β βββ Milvaion.Api/ # REST API, controllers, dashboard
β βββ Sdk/
β β βββ Milvasoft.Milvaion.Sdk/ # Client SDK
β β βββ Milvasoft.Milvaion.Sdk.Worker/ # Worker SDK
β βββ Workers/
β β βββ HttpWorker/ # Built-in HTTP worker
β β βββ SqlWorker/ # Built-in SQL worker
β β βββ EmailWorker/ # Built-in Email worker
β β βββ MilvaionMaintenanceWorker/ # Maintenance jobs
β βββ MilvaionUI/ # React dashboard
βββ tests/
β βββ Milvaion.UnitTests/
β βββ Milvaion.IntegrationTests/
βββ docs/
β βββ portaldocs/ # User documentation
β βββ githubdocs/ # Developer documentation
βββ build/ # Build scripts
Build Order: Domain β Application β Infrastructure β Api β Tests
- .NET 10 SDK
- PostgreSQL 16
- Redis 7
- RabbitMQ 3.x
- Node.js 18+ (for UI development)
# Clone repository
git clone https://github.com/Milvasoft/milvaion.git
cd milvaion
# Start infrastructure (PostgreSQL, Redis, RabbitMQ)
docker compose -f docker-compose.infra.yml up -d
# Run the API
cd src/Milvaion.Api
dotnet run
# Run a worker (in another terminal)
cd src/Workers/SampleWorker
dotnet run# Unit tests
dotnet test tests/Milvaion.UnitTests
# Integration tests (requires infrastructure)
dotnet test tests/Milvaion.IntegrationTests
# All tests with coverage
dotnet test --collect:"XPlat Code Coverage"cd build
# Build all images
./build-all.ps1 -Registry "milvasoft" -Tag "1.0.0"
# Build API only
./build-api.ps1 -Registry "milvasoft" -Tag "1.0.0"
# Build Worker only
./build-worker.ps1 -Registry "milvasoft" -Tag "1.0.0"dotnet new install Milvasoft.Templates.Milvaiondotnet new milvaion-console-worker -n MyCompany.MyWorker
cd MyCompany.MyWorkerusing Milvasoft.Milvaion.Sdk.Worker.Abstractions;
public class MyCustomJob : IAsyncJob
{
private readonly IMyService _myService;
public MyCustomJob(IMyService myService)
{
_myService = myService;
}
public async Task ExecuteAsync(IJobContext context)
{
context.LogInformation("Starting my custom job...");
var data = JsonSerializer.Deserialize<MyJobData>(context.Job.JobData);
await _myService.ProcessAsync(data, context.CancellationToken);
context.LogInformation("Job completed successfully!");
}
}| Document | Description |
|---|---|
| Introduction | What is Milvaion, when to use it |
| Quick Start | Get running in under 10 minutes |
| Core Concepts | Architecture and key terms |
| Your First Worker | Create a custom worker |
| Implementing Jobs | Advanced job patterns |
| Configuration | All configuration options |
| Deployment | Docker and Kubernetes deployment |
| Reliability | Retry, DLQ, zombie detection |
| Scaling | Horizontal scaling strategies |
| Monitoring | Health checks, metrics, logging |
| Document | Description |
|---|---|
| Contributing | How to contribute |
| Architecture | Technical architecture deep-dive |
| Development | Development environment setup |
| API Reference | REST API documentation |
| Worker SDK | Worker SDK reference |
| Security | Security policies |
| Component | Technology |
|---|---|
| Backend | .NET 10, ASP.NET Core |
| Database | PostgreSQL 16, Entity Framework Core |
| Cache/Scheduling | Redis 7 |
| Message Queue | RabbitMQ 3.x |
| Frontend | React, TypeScript, Vite |
| Real-time | SignalR |
| Logging | Serilog, Seq |
| Metrics | OpenTelemetry, Prometheus, Grafana |
| Testing | xUnit, FluentAssertions, Testcontainers |
| CI/CD | GitHub Actions, Docker |
- CQRS: MediatR, Milvasoft.Components.CQRS
- Data Access: Npgsql.EntityFrameworkCore.PostgreSQL, Milvasoft.DataAccess.EfCore
- Authentication: JWT Bearer, Milvasoft.Identity
- API: Asp.Versioning.Mvc, Scalar (OpenAPI)
- Validation: FluentValidation
- Messaging: RabbitMQ.Client
- CQRS (Command Query Responsibility Segregation)
- Mediator Pattern
- Repository Pattern
- Factory Pattern
- Outbox Pattern (for offline resilience)
- Leader Election (for dispatcher)
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
dotnet test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please read our Code of Conduct before contributing.
This project is licensed under the MIT License - see the LICENSE file for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions
Made with β€οΈ by Milvasoft


