Stop Containerizing Your 50-Line Scripts
Source: Dev.to

Introduction
We’ve all been there. You need to deploy a simple webhook handler — maybe 50 lines of code. What do you do?
- Write a Dockerfile
- Set up
docker‑compose.yml - Pull a 500 MB Node.js base image
- Install dependencies
- Configure environment variables
- Set up a reverse proxy
For 50 lines of code.
Your VPS bloats with container layers. Each micro‑task runs in its own Node.js process eating RAM. Updating a single line feels like a deployment ritual.
What if there was a simpler way?
M3M (Mini Services Manager) is a single Go binary that acts as a private runtime for your JavaScript services. No containers. No npm dependency hell. No cloud bills for things that should run on your $5 VPS.
Show Me the Code
$service.boot(() => {
const users = $database.collection('users');
// HTTP Endpoint
$router.get('/users', (ctx) => {
return { users: users.find({}) };
});
$router.post('/users', (ctx) => {
const user = users.insert(ctx.body);
return { user };
});
// Cron Task (Every hour)
$schedule.every('1h', () => {
$logger.info('Total users:', users.count({}));
});
});
$service.start(() => {
$logger.info('Service is ready!');
});
That’s it. No imports. No package.json. No build step. Write it in the browser, hit Save, and it runs.
Built‑in Batteries
Every service has access to powerful modules via the $ prefix:
| Category | Modules |
|---|---|
| Core | $service, $router, $schedule, $logger, $env |
| Data | $database, $storage, $goals |
| Network | $http, $mail |
| Utils | $crypto, $encoding, $utils, $validator |
| Media | $image, $draw |
Routing with Middleware
$service.boot(() => {
// Auth middleware
const auth = (ctx) => {
const token = ctx.header('Authorization');
if (!token) {
ctx.status(401);
return { error: 'Unauthorized' };
}
};
// Protected routes
const api = $router.group('/api', auth);
api.get('/profile', (ctx) => {
return { user: ctx.get('user') };
});
});
Database with MongoDB‑style Queries
const posts = $database.collection('posts');
// Insert
const post = posts.insert({
title: 'Hello World',
views: 0,
tags: ['intro', 'first']
});
// Query with operators
const popular = posts.find({
views: { $gte: 100 },
tags: { $contains: 'featured' }
});
// Update
posts.update(
{ _id: post._id },
{ $inc: { views: 1 } }
);
Scheduled Tasks
// Every 5 minutes
$schedule.every('5m', () => {
$logger.info('Checking for updates...');
});
// Cron expression
$schedule.cron('0 9 * * *', () => {
// Every day at 9 AM
sendDailyReport();
});
// One‑time delayed execution
$schedule.after('30s', () => {
$logger.info('30 seconds have passed!');
});
HTTP Client
const response = $http.post(
'https://api.example.com/webhook',
{
event: 'user_signup',
data: { email: 'user@example.com' }
},
{
headers: { 'X-API-Key': $env.get('API_KEY') }
}
);
if (response.ok) {
$logger.info('Webhook sent successfully');
}
Service Lifecycle
M3M services have three lifecycle phases:
// 1. Boot: Initialize routes, schedules, connections
$service.boot(() => {
$router.get('/health', () => ({ status: 'ok' }));
});
// 2. Start: Service is ready, load initial data
$service.start(() => {
$logger.info('Service started!');
});
// 3. Shutdown: Clean up before stopping
$service.shutdown(() => {
$logger.info('Goodbye!');
});
Performance That Makes Sense
M3M runs comfortably on a $5/month VPS with 512 MB RAM — even with 20+ active services. The entire binary (including the web UI) is ~30 MB.
Compare that to a typical setup where each Node.js container takes 100–200 MB minimum.
Getting Started
Install
# Clone
git clone https://github.com/levskiy0/m3m.git
cd m3m
# Build (requires Go 1.24+, Node.js 20+)
make build
# Create first admin user
./build/m3m new-admin admin@example.com yourpassword
# Run
./build/m3m serve
Real‑World Use Cases
M3M shines for:
- Webhook handlers – Receive and process webhooks from Stripe, GitHub, etc.
- Telegram/Discord bots – Self‑hosted bots without the container tax
- Internal APIs – Quick REST APIs for your tools
- Scheduled tasks – Cron jobs with a nice UI
- Data processors – ETL pipelines, scrapers, aggregators
- Monitoring – Health checks, alerting, metrics collection
Claude Code Integration
M3M includes an MCP server for Claude Code. Once connected, Claude knows the entire M3M API and can help write your services:
make build-mcp
claude mcp add m3m-api ./build/m3m-mcp
Now you can ask Claude: “Write me an M3M service that monitors …” and get a ready‑to‑run implementation.
**M3M** – *“Make My Monitor”* – is a tiny, single‑file Node.js utility that:
- **Monitors a website** and sends alerts via email when it’s down.
- Generates working code using the correct `$http`, `$schedule`, and `$mail` modules.
The Philosophy
M3M is for developers who want to:
- Write logic in the browser, hit Save, and walk away.
- Avoid managing Docker for every 50‑line script.
- Keep server resources for actual work.
- Dodge npm dependency hell for micro‑tasks.
It’s not trying to replace Kubernetes or compete with serverless platforms.
M3M is a practical tool for the practical developer who has better things to do than write Dockerfiles.
