backpulse
v1.0.0
Published
Enterprise-grade multi-database backup library with Cloudflare R2 storage, single-bundle zip archiving, retention policy, and built-in cron scheduler
Downloads
168
Maintainers
Readme
backpulse
Enterprise-grade Multi-Database Backup Library with Cloudflare R2 storage, single-bundle zip archiving, retention policy, and built-in cron scheduler.
Highlights
- 📦 Single-Bundle Multi-Database: Back up MySQL, PostgreSQL, MongoDB, and SQLite simultaneously into a single
.zipsnapshot with an auto-generatedmanifest.json. - 🔒 100% Strictly Private Cloudflare R2: Secure direct streaming upload to R2 with private bucket storage. Public access is disabled by design. Zero egress fees.
- 🎯 Typo-Resistant & Strongly Typed: Zero
anytypes. Discriminated union types with autocomplete + runtime Levenshtein distance typo detection (e.g. suggests "Did you mean 'mysql'?"). - 🧹 Smart Retention Policy: Optional file-limit retention (e.g. keep 10 newest backups; file 11 automatically prunes the oldest). Default is never delete unless explicitly configured.
- ⏰ Built-in Cronjob Scheduler: Robust scheduling powered by
cronerwith timezone support and overlapping run protection. - 🚀 Zero Local Leaks: Automatically dumps to an isolated staging directory and completely scrubs all temporary files after upload.
- 🛡️ Fully Typed: Written 100% in TypeScript with comprehensive declarations (
.d.ts), CJS and ESM dual build.
Installation
npm install backpulse
# or
yarn add backpulse
# or
pnpm add backpulseQuick Start
import { Backpulse, R2Adapter } from 'backpulse';
const backup = new Backpulse({
// 1. Cloudflare R2 Storage Adapter
adapter: new R2Adapter({
accountId: process.env.R2_ACCOUNT_ID!,
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
bucket: 'my-database-backups',
folder: 'production/snapshots', // Destination folder on R2
}),
// 2. Configure one or multiple databases
databases: {
// MySQL Database
main_db: {
type: 'mysql',
connection: {
host: process.env.DB_HOST || 'localhost',
port: 3306,
user: 'root',
password: process.env.DB_PASSWORD,
database: 'app_production',
},
},
// MongoDB Database
logs_db: {
type: 'mongodb',
connection: {
uri: process.env.MONGO_URI || 'mongodb://localhost:27017/app_logs',
},
},
},
// 3. Zip filename template
fileName: 'app_backup_{timestamp}.zip',
// 4. Retention Policy: Keep 10 newest files, auto-delete oldest on 11th
// (If omitted, NO files are ever deleted from R2)
retention: {
maxFiles: 10,
},
// 5. Built-in Cronjob: 02:00 AM daily
cron: '0 2 * * *',
timezone: 'Asia/Ho_Chi_Minh',
});
// Start scheduled backups
backup.start();
// Or run immediately on demand:
// const result = await backup.run();
// console.log(`Backup uploaded to ${result.key} (${result.sizeBytes} bytes)`);Single Bundle Archive Structure
When Backpulse runs, all configured databases are dumped and bundled into one single .zip file on Cloudflare R2:
📦 app_backup_2026-09-05T02-00-00.zip
├── 📄 main_db.sql # MySQL dump
├── 📄 logs_db.archive # MongoDB mongodump
└── 📋 manifest.json # Snapshot metadataManifest Metadata (manifest.json)
{
"version": "1.0.0",
"timestamp": "2026-09-05T02:00:00.000Z",
"durationMs": 4250,
"databases": [
{
"name": "main_db",
"type": "mysql",
"archiveFileName": "main_db.sql",
"sizeBytes": 15423812,
"durationMs": 2100
},
{
"name": "logs_db",
"type": "mongodb",
"archiveFileName": "logs_db.archive",
"sizeBytes": 8920140,
"durationMs": 1950
}
]
}Database Configuration Guide
[!TIP] Typo Protection: Backpulse accepts canonical types as well as standard aliases (
mariadbfor MySQL,postgresqlfor Postgres,mongofor MongoDB,sqlite3for SQLite). If a typo is accidentally entered (e.g.mysqll), Backpulse will catch it at runtime and suggest the correct database type!
1. MySQL / MariaDB (type: 'mysql' or 'mariadb')
Requires mysqldump CLI installed on the system.
databases: {
mysql_db: {
type: 'mysql', // or 'mariadb'
// Either an object:
connection: {
host: '127.0.0.1',
port: 3306,
user: 'root',
password: 'password',
database: 'my_db',
},
// Or a connection URI string:
// connection: 'mysql://root:[email protected]:3306/my_db',
// Optional options:
tables: ['users', 'orders'], // Specific tables only
excludeTables: ['audit_logs'], // Exclude tables
outputName: 'custom_mysql_name', // Output name inside zip
}
}2. PostgreSQL
Requires pg_dump CLI installed on the system.
databases: {
pg_db: {
type: 'postgres',
connection: {
host: '127.0.0.1',
port: 5432,
user: 'postgres',
password: 'password',
database: 'my_pg_db',
},
// Or URI: 'postgresql://postgres:[email protected]:5432/my_pg_db'
}
}3. MongoDB
Requires mongodump CLI installed on the system.
databases: {
mongo_db: {
type: 'mongodb',
connection: {
uri: 'mongodb://admin:secret@localhost:27017/analytics?authSource=admin',
},
}
}4. SQLite
Safe online backup with hot WAL support. Zero CLI dependencies required!
databases: {
sqlite_db: {
type: 'sqlite',
connection: {
filePath: './data/database.sqlite',
},
}
}Retention Policy
The retention policy is completely optional. If you do not configure retention, no files will ever be deleted from your R2 storage.
retention: {
maxFiles: 10, // Keeps the 10 newest backups in the destination folder
prefixMatch: true, // Only targets files matching the fileName prefix
}When file count exceeds maxFiles (e.g. 11 files exist), Backpulse finds the oldest files by LastModified and deletes them from R2.
Cron Scheduler
Backpulse uses croner for rock-solid cron scheduling:
const backup = new Backpulse({
// ...
cron: '0 3 * * *', // Every day at 3:00 AM
timezone: 'Asia/Ho_Chi_Minh', // Any IANA timezone
runOnStart: false, // Trigger an initial run when start() is called
});
// Start scheduler
backup.start();
// Check next run time
console.log('Next scheduled run:', backup.nextRun());
// Stop scheduler
backup.stop();Filename Template Tokens
The fileName option supports the following dynamic tokens:
| Token | Description | Example |
| :--- | :--- | :--- |
| {timestamp} | Full ISO-safe timestamp | 2026-09-05T14-30-00 |
| {date} | Date string | 2026-09-05 |
| {year} | 4-digit Year | 2026 |
| {month} | 2-digit Month | 09 |
| {day} | 2-digit Day | 05 |
| {hours} | 2-digit Hour | 14 |
| {minutes} | 2-digit Minute | 30 |
License
MIT © Phan Hieu
