A high-performance, lightweight SMS testing server with a beautiful real-time web dashboard. Perfect for development, testing, and load testing SMS integrations without making actual API calls or incurring costs.
- ๐ High Performance - Handle 10,000+ SMS/second
- ๐จ Beautiful Web Dashboard - Real-time message monitoring
- ๐ Auto-Refresh - Dashboard updates every 2 seconds
- ๐ Performance Testing - Built-in load testing capabilities
- ๐ณ Docker Support - Containerized deployment ready
- ๐ Simple API - RESTful endpoints for easy integration
- ๐พ In-Memory Storage - No database required
- ๐ CORS Enabled - Works with any frontend
- โก Cluster Mode - Multi-core support for maximum throughput
- ๐ Health Checks - Monitor system status
- Node.js >= 14.0.0
- npm >= 6.0.0
# Clone or download the repository
cd sms-simulator-ali
# Install dependencies
npm install
# Start the server
npm startThe server will start on http://localhost:3030
Visit http://localhost:3030 in your browser to see the real-time dashboard.
Endpoint: POST http://localhost:3030/api/sms
Request Body:
{
"to": "+1234567890",
"from": "+0987654321",
"body": "Your message here"
}Response:
{
"success": true,
"messageId": "sms-1700000000000",
"message": "SMS queued for delivery"
}| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Web dashboard |
POST |
/api/sms |
Send SMS message |
GET |
/api/messages |
Get all messages |
GET |
/api/messages/:id |
Get specific message |
DELETE |
/api/messages |
Clear all messages |
GET |
/health |
Health check |
# Send SMS
curl -X POST http://localhost:3030/api/sms \
-H "Content-Type: application/json" \
-d '{"to":"+1234567890","from":"TestApp","body":"Hello World!"}'
# View all messages
curl http://localhost:3030/api/messages
# Clear messages
curl -X DELETE http://localhost:3030/api/messages
# Health check
curl http://localhost:3030/healthconst axios = require('axios');
// Send SMS
const response = await axios.post('http://localhost:3030/api/sms', {
to: '+1234567890',
from: 'MyApp',
body: 'Test message'
});
console.log(response.data);import requests
# Send SMS
response = requests.post('http://localhost:3030/api/sms', json={
'to': '+1234567890',
'from': 'MyApp',
'body': 'Test message'
})
print(response.json())<?php
$data = [
'to' => '+1234567890',
'from' => 'MyApp',
'body' => 'Test message'
];
$ch = curl_init('http://localhost:3030/api/sms');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
print_r(json_decode($response));
?># Change port (default: 3030)
PORT=3031 npm start
# Enable debug logging
DEBUG=* npm start
# Increase Node.js memory limit
NODE_OPTIONS="--max-old-space-size=4096" npm startFor high-performance scenarios, use cluster mode:
npm run clusterThis will spawn one worker process per CPU core for maximum throughput.
npm run docker:buildnpm run docker:runOr manually:
docker run -d \
-p 3030:3030 \
--name sms-simulator \
sms-simulator-aliversion: '3.8'
services:
sms-simulator:
build: .
ports:
- "3030:3030"
environment:
- NODE_ENV=production
restart: unless-stopped# Test with 1,000 messages (default)
npm test
# Test with 10,000 messages, batch size 100
node tests/test-load.js 10000 100
# Test with 50,000 messages, batch size 200
node tests/test-load.js 50000 200# Create test payload
cat > sms-payload.json << 'EOF'
{"to":"+1234567890","from":"LoadTest","body":"Test message"}
EOF
# Run load test (10,000 requests, 100 concurrent)
ab -n 10000 -c 100 -p sms-payload.json -T application/json \
http://localhost:3030/api/smsOn standard hardware (4-core CPU, 8GB RAM):
| Scenario | Messages | Concurrency | Throughput | Avg Latency |
|---|---|---|---|---|
| Light Load | 1,000 | 10 | 833/sec | 12ms |
| Normal Load | 10,000 | 50 | 2,222/sec | 22ms |
| Peak Load | 50,000 | 100 | 2,778/sec | 36ms |
| Stress Test | 100,000 | 200 | 2,222/sec | 90ms |
For detailed performance testing guide, see PERFORMANCE_TESTING.md
# Install PM2
npm install -g pm2
# Start server
npm run pm2:start
# Monitor
pm2 monit
# View logs
npm run pm2:logs
# Restart
npm run pm2:restart
# Stop
npm run pm2:stopFor production deployments handling high loads:
Increase file descriptor limits:
ulimit -n 65536Optimize TCP settings (Linux):
sudo sysctl -w net.core.somaxconn=1024
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048curl http://localhost:3030/healthResponse:
{
"status": "healthy",
"uptime": 3600.5,
"messageCount": 1250,
"timestamp": "2025-11-24T14:30:00.000Z"
}The web dashboard displays:
- Total message count
- Server status
- Uptime
- Live message feed
- Auto-refresh every 2 seconds
sms-simulator-ali/
โโโ server.js # Main application
โโโ server-cluster.js # Cluster mode support
โโโ package.json # Dependencies
โโโ README.md # This file
โโโ PERFORMANCE_TESTING.md # Performance guide
โโโ Dockerfile # Docker image
โโโ .dockerignore # Docker ignore rules
โโโ .gitignore # Git ignore rules
โโโ tests/
โ โโโ test-load.js # Load testing script
โโโ examples/
โโโ sms-payload.json # Sample payloads
โโโ artillery-config.yml # Artillery test config
โโโ k6-test.js # k6 test script
Node.js/Express:
const axios = require('axios');
async function sendSMS(to, message) {
const SMS_API = process.env.SMS_API_URL || 'http://localhost:3030/api/sms';
try {
const response = await axios.post(SMS_API, {
to: to,
from: 'MyApp',
body: message
});
return response.data;
} catch (error) {
console.error('Failed to send SMS:', error.message);
throw error;
}
}
// Usage
await sendSMS('+1234567890', 'Welcome to our service!');Python/Django:
import requests
def send_sms(to, message):
SMS_API = os.getenv('SMS_API_URL', 'http://localhost:3030/api/sms')
try:
response = requests.post(SMS_API, json={
'to': to,
'from': 'MyApp',
'body': message
})
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f'Failed to send SMS: {e}')
raiseJava/Spring Boot:
@Service
public class SmsService {
private final RestTemplate restTemplate;
private final String smsApiUrl;
public SmsService() {
this.restTemplate = new RestTemplate();
this.smsApiUrl = System.getenv().getOrDefault(
"SMS_API_URL", "http://localhost:3030/api/sms"
);
}
public Map<String, Object> sendSMS(String to, String message) {
Map<String, String> request = new HashMap<>();
request.put("to", to);
request.put("from", "MyApp");
request.put("body", message);
return restTemplate.postForObject(smsApiUrl, request, Map.class);
}
}# Find process using port 3030
lsof -i :3030
# Kill process
kill -9 <PID>
# Or use a different port
PORT=3031 npm startThe simulator stores the last 100 messages in memory. For extended testing:
- Periodically clear messages via API
- Increase Node.js memory limit
- Use cluster mode for better memory distribution
- Ensure the server is running
- Check firewall settings
- Verify the port is correct
- Check if another service is using the port
POST /api/sms
Request:
{
"to": "string | string[]", // Required: Phone number(s)
"from": "string", // Optional: Sender ID
"body": "string", // Optional: Message content
"message": "string" // Optional: Alternative to body
}Response:
{
"success": true,
"messageId": "sms-1700000000000",
"message": "SMS queued for delivery"
}GET /api/messages
Response:
[
{
"id": "sms-1700000000000",
"to": "+1234567890",
"from": "+0987654321",
"body": "Message content",
"timestamp": "2025-11-24T14:30:00.000Z",
"status": "delivered"
}
]DELETE /api/messages
Response:
{
"success": true,
"message": "All messages cleared (25 total)"
}GET /health
Response:
{
"status": "healthy",
"uptime": 3600.5,
"messageCount": 1250,
"timestamp": "2025-11-24T14:30:00.000Z"
}This simulator is designed for development and testing purposes. For production use:
- Implement authentication
- Add rate limiting
- Enable HTTPS/TLS
- Restrict CORS origins
- Add input validation
- Implement logging and monitoring
MIT License
Copyright (c) 2025 Ali Saberi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Ali Saberi
- Email: ali@utilli.com
- Company: Tilli Software
- Website: https://tillisoftware.com
Created for the development and testing needs of the Tilli Software team.
For questions, issues, or feature requests:
- Open an issue on GitHub
- Email: ali@utilli.com
- Documentation: See PERFORMANCE_TESTING.md
Made with โค๏ธ by Ali Saberi for the developer community