A scalable, event-driven backend system that executes and evaluates user-submitted code against multiple test cases — inspired by platforms like LeetCode and HackerRank.
This project simulates a real-world online judge system, supporting:
- Asynchronous code submission processing
- Multi-test-case evaluation
- Event-driven microservices architecture (Kafka)
- Persistent storage using MongoDB
- Language execution (Python supported)
flowchart TD
A[Client Submit Request] --> B[Node API]
B --> C[Create Submission]
C -->|Persist Submission| D[(MongoDB)]
C -->|Emit Event: code.submitted| E[Kafka Topic]
E --> F[Spring Boot Consumer]
F -->|Fetch Submission| D
F -->|Fetch Problem & Test Cases| D
F --> G[Execution Engine]
G -->|Run Code per Test Case| H[Python Runtime]
H -->|Stdout / Stderr| G
G -->|Evaluate Output| I[Result Aggregator]
I -->|Persist Execution Result| D
I -->|Update Submission Status| D
D --> J[Client Fetch Result]
- User submits code via REST API
- Submission is stored in MongoDB
- Event is published to Kafka
- Spring Boot service consumes event
- Fetches problem + test cases
- Executes code against each test case
- Evaluates output
- Stores result and updates submission status
- Node.js (API Gateway)
- Spring Boot (Execution Engine)
- Apache Kafka
- MongoDB
- Python (via ProcessBuilder)
node-api/
├── routes/
├── models/
├── kafka/
└── controllers/
code-executor/
├── kafka/
├── services/
├── model/
├── repository/
└── config/
{
"_id": "ObjectId",
"userId": "string",
"problemId": "string",
"code": "string",
"language": "python",
"status": "PENDING | RUNNING | SUCCESS | FAILED"
}{
"title": "Sum of Two Numbers",
"description": "Add two integers",
"difficulty": "EASY",
"tags": ["MATHS"],
"testCases": [
{
"input": "2 3",
"expectedOutput": "5",
"isHidden": false
}
]
}{
"submissionId": "string",
"status": "SUCCESS | FAILED | PARTIAL",
"testCasesPassed": 2,
"totalTestCases": 2,
"error": null
}POST /api/submit
{
"userId": "661f123abc123abc123abc12",
"problemId": "PROBLEM_ID",
"language": "python",
"code": "a, b = map(int, input().split()); print(a + b)"
}{
"message": "Submission received",
"submissionId": "..."
}For each test case:
- Execute user code in isolated process
- Provide input via stdin
- Capture stdout and stderr
- Normalize output formatting
- Compare against expected output
| Condition | Status |
|---|---|
| All Test Passed | SUCCESS |
| No Test Passed | FAILED |
| Some Test Passed | PARTIAL |
- Handling blocking stdin in runtime execution
- Ensuring inter-service data consistency
- Debugging asynchronous Kafka workflows
- Managing process lifecycle and output capture
- Normalizing output across environments
- Prerequisites
- Node.js
- Java 21+
- Maven
- MongoDB
- Docker (for Kafka)
- Event-driven execution pipeline
- Multi-test-case validation
- Persistent result tracking
- Scalable microservice architecture
- Clean separation of concerns
- Time Limit Enforcement (TLE)
- Memory usage tracking
- Docker-based sandbox execution
- Multi-language support (Java, C++, Go)
- Rate limiting and submission throttling
- Execution queue prioritization
- Monitoring & observability (metrics/logging)
Developed as a backend system design project demonstrating distributed systems, event-driven architecture, and execution engine design.
- Practical implementation of Kafka-based communication
- Real-world debugging of async systems
- Process execution and lifecycle handling
- Database consistency across services
- Scalable backend design patterns
If you find this project valuable, consider giving it a ⭐ on GitHub.