milodb
v2.0.0
Published
Fast encrypted JSON database with AI-friendly API
Downloads
143
Maintainers
Readme
MiloDB 🚀
Fast, encrypted JSON database for small projects and serverless apps
Zero-config database that works out of the box. No setup, no servers, no complexity.
Why MiloDB?
Perfect for small projects, prototypes, and serverless apps where traditional databases are overkill:
✅ Zero Setup - No installation, no configuration, no servers
✅ Serverless Ready - Works in Next.js, Vercel, Netlify
✅ Encrypted - AES-256-GCM encryption built-in
✅ Fast - Indexed lookups, batch operations, streaming
✅ TypeScript - Full type safety and autocomplete
✅ AI-Friendly - Simple API that LLMs understand
✅ Tiny - No dependencies on external databases
When to Use MiloDB
✅ Perfect for:
- Side projects and MVPs
- Serverless functions (Next.js, Vercel, Netlify)
- Prototypes and demos
- Small apps (<100k records per table)
- Local development
- Configuration storage
- Cache layer
❌ Not for:
- High-traffic production apps (>1M requests/day)
- Complex queries (joins, aggregations)
- Multi-server deployments
- Real-time collaboration
Installation
npm install milodbQuick Start
import MiloDB from 'milodb';
// Initialize (no encryption)
const db = new MiloDB();
// Or with encryption
const db = new MiloDB('./data', 'your-secret-key');
// Create table
await db.createTable('users');
// Insert
await db.insert('users', {
id: 1,
name: 'Alice',
email: '[email protected]'
});
// Find
const users = await db.find('users', { name: 'Alice' });
// Update
await db.update('users', 1, { email: '[email protected]' });
// Delete
await db.delete('users', 1);Complete API
Tables
// Create table
await db.createTable('products');
// List all tables
const tables = await db.listTables();
// ['users', 'products']
// Drop table
await db.dropTable('products');Insert
// Single insert
await db.insert('users', {
id: 1,
name: 'Bob',
role: 'admin'
});
// Batch insert (10x faster)
await db.insertMany('users', [
{ id: 2, name: 'Charlie', role: 'user' },
{ id: 3, name: 'Diana', role: 'user' }
]);Query
// Find all
const all = await db.find('users');
// Find with filter
const admins = await db.find('users', { role: 'admin' });
// Find by ID (indexed, instant)
const user = await db.findById('users', 1);
// Pagination & sorting
const page = await db.find('users',
{ role: 'user' },
{
limit: 10,
offset: 20,
sort: 'name',
order: 'asc'
}
);
// Count
const total = await db.count('users', { role: 'admin' });Update
// Update single
await db.update('users', 1, { role: 'superadmin' });
// Update multiple
const updated = await db.updateMany(
'users',
{ role: 'user' },
{ active: true }
);
console.log(`Updated ${updated} records`);Delete
// Delete single
await db.delete('users', 1);
// Delete multiple
const deleted = await db.deleteMany('users', { active: false });
console.log(`Deleted ${deleted} records`);Real-World Examples
1. Next.js Blog (Serverless)
// app/api/posts/route.ts
import { MiloDB } from 'milodb';
const db = new MiloDB('./data');
export async function GET() {
const posts = await db.find('posts', {}, {
sort: 'createdAt',
order: 'desc',
limit: 10
});
return Response.json(posts);
}
export async function POST(req: Request) {
const post = await req.json();
await db.insert('posts', {
...post,
id: Date.now(),
createdAt: new Date().toISOString()
});
return Response.json({ success: true });
}2. E-commerce Store
import MiloDB from 'milodb';
const db = new MiloDB('./store', process.env.DB_KEY);
// Setup
await db.createTable('products');
await db.createTable('orders');
// Add products
await db.insertMany('products', [
{ id: 1, name: 'Laptop', price: 999, stock: 50 },
{ id: 2, name: 'Mouse', price: 29, stock: 200 },
{ id: 3, name: 'Keyboard', price: 79, stock: 150 }
]);
// Search products
const affordable = await db.find('products', {}, {
sort: 'price',
order: 'asc',
limit: 5
});
// Create order
await db.insert('orders', {
id: Date.now(),
userId: 123,
items: [1, 2],
total: 1028,
status: 'pending'
});
// Update stock
await db.update('products', 1, { stock: 49 });
// Get pending orders
const pending = await db.count('orders', { status: 'pending' });3. User Authentication
import MiloDB from 'milodb';
import bcrypt from 'bcrypt';
const db = new MiloDB('./auth', process.env.SECRET);
await db.createTable('users');
// Register
async function register(email: string, password: string) {
const hash = await bcrypt.hash(password, 10);
await db.insert('users', {
id: Date.now(),
email,
password: hash,
createdAt: new Date().toISOString()
});
}
// Login
async function login(email: string, password: string) {
const users = await db.find('users', { email });
if (!users.length) return null;
const valid = await bcrypt.compare(password, users[0].password);
return valid ? users[0] : null;
}4. API Rate Limiting
import MiloDB from 'milodb';
const db = new MiloDB('./cache');
await db.createTable('ratelimit');
async function checkRateLimit(ip: string): Promise<boolean> {
const now = Date.now();
const hour = 60 * 60 * 1000;
const requests = await db.find('ratelimit', {
ip,
timestamp: { $gt: now - hour }
});
if (requests.length >= 100) return false;
await db.insert('ratelimit', {
id: Date.now(),
ip,
timestamp: now
});
return true;
}5. Configuration Management
import MiloDB from 'milodb';
const db = new MiloDB('./config', 'config-key');
await db.createTable('settings');
// Save settings
await db.insert('settings', {
id: 'app',
theme: 'dark',
language: 'en',
notifications: true
});
// Load settings
const config = await db.findById('settings', 'app');
// Update setting
await db.update('settings', 'app', { theme: 'light' });TypeScript Support
Full type safety with generics:
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user';
}
const users = await db.find<User>('users', { role: 'admin' });
// users is typed as User[]
const user = await db.findById<User>('users', 1);
// user is typed as User | nullEncryption
MiloDB uses AES-256-GCM with proper key derivation (PBKDF2):
// Enable encryption
const db = new MiloDB('./secure-data', 'your-strong-password');
// All operations are encrypted automatically
await db.insert('secrets', { apiKey: 'sk-...' });
// Data is encrypted at rest
// Only decrypted in memory during operationsSecurity Notes:
- Store encryption key in environment variables
- Use strong passwords (16+ characters)
- Encryption adds ~20% overhead
- Keys are derived using PBKDF2 (100k iterations)
Performance
Benchmarks (M1 Mac, 10k records):
| Operation | Time | Records/sec | |-----------|------|-------------| | Insert | 0.5ms | 2,000/sec | | Batch Insert (100) | 15ms | 6,600/sec | | Find by ID | 0.1ms | 10,000/sec | | Find with filter | 5ms | 2,000/sec | | Update | 8ms | 125/sec | | Delete | 8ms | 125/sec |
Tips:
- Use
insertMany()for bulk inserts (10x faster) - Use
findById()for single lookups (indexed) - Enable encryption only if needed (~20% slower)
- Use pagination for large result sets
CLI
# Initialize database
npx milodb init
# Follow prompts:
# - Enable encryption? (y/n)
# - Encryption key: ********
# - Create users table? (y)
# Creates:
# - ./db/ folder
# - milo.config.jsonDashboard (Optional)
Visual dashboard for managing data:
cd node_modules/milodb/dashboard
npm install
npm run devOpen http://localhost:3000 for GUI management.
Comparison
| Feature | MiloDB | SQLite | MongoDB | PostgreSQL | |---------|--------|--------|---------|------------| | Setup | ✅ None | ⚠️ Binary | ❌ Server | ❌ Server | | Serverless | ✅ Yes | ⚠️ Limited | ❌ No | ❌ No | | Encryption | ✅ Built-in | ❌ No | ⚠️ Enterprise | ⚠️ Extension | | TypeScript | ✅ Native | ⚠️ Wrapper | ⚠️ Wrapper | ⚠️ Wrapper | | File-based | ✅ JSON | ✅ Binary | ❌ No | ❌ No | | Learning Curve | ✅ 5 min | ⚠️ 1 hour | ❌ 1 day | ❌ 1 week |
Migration Path
Start with MiloDB, migrate later if needed:
// Export data
const users = await db.find('users');
await fs.writeJson('export.json', users);
// Import to PostgreSQL/MongoDB
// Your data is just JSON!FAQ
Q: Is this production-ready?
A: Yes, for small projects (<100k records, <10k requests/day). Not for high-traffic apps.
Q: Can I use this with Vercel/Netlify?
A: Yes! Perfect for serverless functions. Data persists in your repo.
Q: How do I backup?
A: Just copy the ./db folder. It's plain JSON files (or encrypted).
Q: Can multiple processes access the same database?
A: No. MiloDB is single-process. Use Redis/PostgreSQL for multi-process.
Q: What about data corruption?
A: MiloDB uses atomic writes. Corruption is rare but possible. Keep backups.
Q: Performance with large datasets?
A: Works well up to 100k records per table. Beyond that, consider PostgreSQL.
License
MIT
Contributing
Issues and PRs welcome! This is a simple project - keep it simple.
Made for developers who want to build fast, not configure databases.
Start coding in 30 seconds:
npm install milodb