A comprehensive suite of database backup tools supporting PostgreSQL, MySQL, MariaDB, and MongoDB with multiple backup methods.
Professional-grade interactive backup tool with Clean Architecture principles.
Lightweight, configuration-based backup scripts for automation.
A professional-grade database backup tool built with Clean Architecture principles in Go.
This project follows Clean Architecture (also known as Hexagonal Architecture or Ports and Adapters), ensuring:
- Independence of Frameworks: Business logic doesn't depend on external libraries
- Testability: Business rules can be tested without UI, database, or external elements
- Independence of UI: Easy to change UI without changing business logic
- Independence of Database: Business rules aren't bound to backup mechanisms
- Independence of External Agents: Business rules don't know about the outside world
cmd/backup/ # Application entry point
└── main.go # Dependency injection & wiring
internal/
├── domain/ # Enterprise Business Rules (Entities)
│ ├── entity.go # Domain entities and value objects
│ ├── repository.go # Repository interfaces (ports)
│ └── service.go # Service interfaces (ports)
│
├── usecase/ # Application Business Rules
│ └── backup_usecase.go # Orchestrates backup workflow
│
├── infrastructure/ # Frameworks & Drivers (Adapters)
│ └── backup_repository.go # Docker/kubectl implementation
│
└── delivery/ # Interface Adapters
└── cli/
├── config_service.go # User input handling
└── output_service.go # Output formatting
.
├── cmd/
│ └── backup/
│ └── main.go # Application entry point
│
├── internal/
│ ├── domain/ # Domain Layer (innermost)
│ │ ├── entity.go # Core entities
│ │ ├── repository.go # Repository interface
│ │ └── service.go # Service interfaces
│ │
│ ├── usecase/ # Use Case Layer
│ │ └── backup_usecase.go # Business logic
│ │
│ ├── infrastructure/ # Infrastructure Layer (outermost)
│ │ └── backup_repository.go # External tool implementation
│ │
│ └── delivery/ # Delivery Layer (outermost)
│ └── cli/
│ ├── config_service.go # CLI input handler
│ └── output_service.go # CLI output handler
│
├── go.mod
└── README.md
Location: internal/domain/
Responsibility: Core business entities and interfaces
Dependencies: None (pure business logic)
Files:
entity.go: Defines core entities (DatabaseConfig, BackupConfig, BackupResult)repository.go: Defines BackupRepository interface (port)service.go: Defines ConfigService and OutputService interfaces (ports)
Example:
// Domain entity - no dependencies
type DatabaseConfig struct {
Type DatabaseType
Host string
Database string
// ...
}
// Repository interface (port) - defines what we need, not how
type BackupRepository interface {
BackupPostgres(config DatabaseConfig, ...) error
BackupMySQL(config DatabaseConfig, ...) error
// ...
}Location: internal/usecase/
Responsibility: Orchestrates business workflows
Dependencies: Only domain layer
Files:
backup_usecase.go: Implements the backup workflow logic
Example:
// Use case depends only on interfaces (dependency inversion)
type BackupUsecase struct {
backupRepo domain.BackupRepository
configService domain.ConfigService
outputService domain.OutputService
}
// Business logic is clean and testable
func (uc *BackupUsecase) ExecuteInteractiveBackup() error {
// 1. Get configuration
// 2. Execute backups
// 3. Report results
}Location: internal/infrastructure/
Responsibility: Implements external integrations
Dependencies: Domain layer (implements interfaces)
Files:
backup_repository.go: Implements BackupRepository using Docker/kubectl
Example:
// Adapter implementing the port
type BackupRepositoryImpl struct{}
// Implements domain.BackupRepository interface
func (r *BackupRepositoryImpl) BackupPostgres(...) error {
// Docker/kubectl specific implementation
}Location: internal/delivery/cli/
Responsibility: Handles user interaction
Dependencies: Domain layer (implements interfaces)
Files:
config_service.go: CLI-based configuration inputoutput_service.go: CLI-based output formatting
Example:
// Adapter implementing the port
type ConfigServiceImpl struct {
reader *bufio.Reader
}
// Implements domain.ConfigService interface
func (s *ConfigServiceImpl) SelectBackupMethod() (domain.BackupMethod, error) {
// CLI-specific input handling
}Location: cmd/backup/main.go
Responsibility: Dependency injection and wiring
Example:
func main() {
// Dependency Injection (all dependencies resolved here)
backupRepo := infrastructure.NewBackupRepository()
configService := cli.NewConfigService()
outputService := cli.NewOutputService()
// Wire up use case
backupUsecase := usecase.NewBackupUsecase(
backupRepo,
configService,
outputService,
)
// Execute
backupUsecase.ExecuteInteractiveBackup()
}go build -o bin/backup ./cmd/backupgo run ./cmd/backup/main.go./bin/backupgo install ./cmd/backup========================================
Interactive Database Backup Tool
Clean Architecture Edition
Supports: PostgreSQL, MySQL, MariaDB, MongoDB
========================================
Select backup method:
1. docker-run (Use temporary container)
2. docker-exec (Exec into existing Docker container)
3. kubectl-exec (Exec into Kubernetes pod)
Enter choice [1-3]: 3
Kubernetes Namespace [default]: production
Select databases to backup:
1. PostgreSQL
2. MySQL
3. MariaDB
4. MongoDB
5. All databases
Enter choices (comma-separated, e.g., 1,2,4): 1
=== Configuring POSTGRES ===
PostgreSQL Host [postgres]: prod-postgres
PostgreSQL User [postgres]: admin
Database Name [mydb]: production_db
PostgreSQL Password: ********
PostgreSQL Version [15]: 15
Pod Name [postgres-0]: postgres-primary-0
=== Configuration Summary ===
Backup Method: kubectl-exec
Timestamp: 2025-11-26 10:21:59
Backup Directory: backup
Kubernetes Namespace: production
Databases to backup:
1. postgres - production_db (Host: prod-postgres)
Proceed with backup? (y/n): y
[POSTGRES] Starting backup...
Method: kubectl-exec
Host: prod-postgres
Database: production_db
Pod: postgres-primary-0
✓ Backup completed: backup/postgres/production_db_2025-11-26_10-22-01.sql (145M) [2.3s]
========================================
Backup Process Completed!
========================================
Results:
Successful: 1
Backup files:
✓ postgres: backup/postgres/production_db_2025-11-26_10-22-01.sql (145M)
Clean Architecture makes testing much easier:
// Test entities and value objects
func TestDatabaseType_IsValid(t *testing.T) {
// Pure business logic testing
}// Mock the dependencies
type MockBackupRepository struct {
mock.Mock
}
func TestBackupUsecase_ExecuteInteractiveBackup(t *testing.T) {
// Test business logic with mocks
mockRepo := new(MockBackupRepository)
mockConfig := new(MockConfigService)
mockOutput := new(MockOutputService)
usecase := NewBackupUsecase(mockRepo, mockConfig, mockOutput)
// Test the workflow
}// Test with real implementations
func TestBackupRepository_BackupPostgres(t *testing.T) {
repo := NewBackupRepository()
// Test actual Docker commands
}main.go (Composition Root)
↓
├─→ infrastructure.BackupRepository (adapter)
├─→ cli.ConfigService (adapter)
├─→ cli.OutputService (adapter)
↓
usecase.BackupUsecase (business logic)
↓ (depends on interfaces only)
├─→ domain.BackupRepository (interface)
├─→ domain.ConfigService (interface)
└─→ domain.OutputService (interface)
Key Principle: Dependencies point inward. Domain has zero dependencies.
- Repository Pattern: Abstracts data access (BackupRepository)
- Service Pattern: Encapsulates operations (ConfigService, OutputService)
- Dependency Injection: All dependencies injected in main.go
- Interface Segregation: Small, focused interfaces
- Single Responsibility: Each layer has one reason to change
- Business logic can be tested without Docker/kubectl
- Mock implementations for all interfaces
- Fast unit tests without external dependencies
- Clear separation of concerns
- Easy to understand structure
- Changes isolated to specific layers
- Swap Docker for direct database connections
- Change from CLI to Web UI without touching business logic
- Add new backup methods without changing use cases
- Add new databases by extending interfaces
- Parallel execution can be added in use case layer
- Easy to add features like scheduling, notifications
- Web UI: Add
internal/delivery/http/without touching business logic - REST API: Add
internal/delivery/api/alongside CLI - Different Storage: Add S3/GCS implementation of repository
- Scheduling: Add scheduler in use case layer
- Monitoring: Add observability in infrastructure layer
- Configuration Files: Add config file parser in delivery layer
// internal/delivery/http/handler.go
type BackupHandler struct {
backupUsecase *usecase.BackupUsecase
}
func (h *BackupHandler) HandleBackup(w http.ResponseWriter, r *http.Request) {
// Same use case, different delivery mechanism
h.backupUsecase.ExecuteInteractiveBackup()
}Lightweight, environment-based backup scripts for automated backups.
Located in scripts/ directory:
backup-all-flexible.sh- Backup all configured databasesbackup-postgres-flexible.sh- PostgreSQL onlybackup-mysql-flexible.sh- MySQL onlybackup-mariadb-flexible.sh- MariaDB onlybackup-mongodb-flexible.sh- MongoDB only
- Copy the example environment file:
cp .env.example .env- Edit
.envwith your configuration:
# Choose backup method
BACKUP_METHOD=kubectl-exec # or docker-run, docker-exec
# For kubectl-exec
K8S_NAMESPACE=production
PG_POD=postgres-primary-0
MYSQL_POD=mysql-primary-0
MARIADB_POD=mariadb-primary-0
MONGO_POD=mongodb-primary-0
# Database credentials
PG_HOST=postgres
PG_USER=postgres
PG_DB=production_db
PG_PASS=secure_password
# ... (configure other databases)- Make scripts executable:
chmod +x scripts/*.sh./scripts/backup-all-flexible.sh./scripts/backup-postgres-flexible.sh
./scripts/backup-mysql-flexible.sh
./scripts/backup-mariadb-flexible.sh
./scripts/backup-mongodb-flexible.shAll scripts support three backup methods:
Uses temporary containers - no running container needed.
BACKUP_METHOD=docker-runBest for:
- Remote databases
- No local database containers
- Clean, isolated backups
Executes commands in existing Docker containers.
BACKUP_METHOD=docker-exec
PG_CONTAINER=test-postgres
MYSQL_CONTAINER=test-mysqlBest for:
- Local Docker databases
- Docker Compose setups
- Development environments
Executes commands in Kubernetes pods.
BACKUP_METHOD=kubectl-exec
K8S_NAMESPACE=production
PG_POD=postgres-0
MYSQL_POD=mysql-0Best for:
- Kubernetes deployments
- Production environments
- Cloud-native setups
backup/
├── postgres/
│ ├── mydb_2025-11-26_10-30-00.sql
│ └── mydb_2025-11-26_14-30-00.sql
├── mysql/
│ ├── mydb_2025-11-26_10-30-00.sql
│ └── mydb_2025-11-26_14-30-00.sql
├── mariadb/
│ └── mydb_2025-11-26_10-30-00.sql
└── mongodb/
└── 2025-11-26_10-30-00/
└── mydb/
├── collection1.bson
└── collection1.metadata.json
BACKUP_METHOD=docker-run|docker-exec|kubectl-exec
BACKUP_TEMP_DIR=/tmp/db-backups # Temp dir for docker-exec/kubectl-execPG_CONTAINER=test-postgres
MYSQL_CONTAINER=test-mysql
MARIADB_CONTAINER=test-mariadb
MONGO_CONTAINER=test-mongodbK8S_NAMESPACE=default
PG_POD=postgres-0
MYSQL_POD=mysql-0
MARIADB_POD=mariadb-0
MONGO_POD=mongodb-0# PostgreSQL
PG_HOST=postgres
PG_USER=postgres
PG_DB=mydb
PG_PASS=password
PG_VERSION=15
# MySQL
MYSQL_HOST=mysql
MYSQL_USER=root
MYSQL_PASS=password
MYSQL_DB=mydb
MYSQL_VERSION=8
# MariaDB
MARIADB_HOST=mariadb
MARIADB_USER=root
MARIADB_PASS=password
MARIADB_DB=mydb
MARIADB_VERSION=11
# MongoDB
MONGO_HOST=mongodb
MONGO_DB=mydb
MONGO_VERSION=7Add to crontab for scheduled backups:
# Daily backup at 2 AM
0 2 * * * cd /path/to/backup-tool && ./scripts/backup-all-flexible.sh
# Every 6 hours
0 */6 * * * cd /path/to/backup-tool && ./scripts/backup-all-flexible.sh
# Weekly backup (Sunday at 3 AM)
0 3 * * 0 cd /path/to/backup-tool && ./scripts/backup-all-flexible.sh$ ./scripts/backup-all-flexible.sh
=========================================
Flexible Database Backup Automation
Method: kubectl-exec
Timestamp: 2025-11-26_10-30-00
=========================================
Creating backup directories...
✓ Directories created
[PostgreSQL] Starting backup...
Method: kubectl-exec
Host: postgres
Database: mydb
User: postgres
Pod: postgres-0
Namespace: production
✓ PostgreSQL backup completed: backup/postgres/mydb_2025-11-26_10-30-00.sql (145M)
[MySQL] Starting backup...
Method: kubectl-exec
Host: mysql
Database: mydb
User: root
Pod: mysql-0
Namespace: production
✓ MySQL backup completed: backup/mysql/mydb_2025-11-26_10-30-00.sql (87M)
========================================
Backup process completed!
========================================
Backup method: kubectl-exec
Backup location: /home/user/backup-tool/backup/
Recent backups:
backup/postgres/mydb_2025-11-26_10-30-00.sql
backup/mysql/mydb_2025-11-26_10-30-00.sqlA docker-compose.yml is provided for testing all database types locally.
docker-compose up -ddocker-compose ps# Configure for docker-exec method
cat > .env << EOF
BACKUP_METHOD=docker-exec
PG_CONTAINER=test-postgres
MYSQL_CONTAINER=test-mysql
MARIADB_CONTAINER=test-mariadb
MONGO_CONTAINER=test-mongodb
PG_HOST=localhost
PG_USER=postgres
PG_DB=mydb
PG_PASS=password
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASS=password
MYSQL_DB=mydb
MARIADB_HOST=localhost
MARIADB_USER=root
MARIADB_PASS=password
MARIADB_DB=mydb
MONGO_HOST=localhost
MONGO_DB=mydb
EOF
# Run backup
./scripts/backup-all-flexible.shdocker-compose downdocker-compose down -v| Feature | Go Tool | Bash Scripts |
|---|---|---|
| Setup | Compile once | Edit .env file |
| User Experience | ✅ Interactive prompts | 📝 Pre-configured |
| Configuration | ✅ Step-by-step | 📝 Environment variables |
| Namespace Support | ✅ Prompted | 📝 K8S_NAMESPACE var |
| Error Handling | ✅ Comprehensive | |
| Flexibility | ✅ High | |
| Automation | ✅ Cron-friendly | |
| Dependencies | Go binary only | Bash + tools |
| Cross-platform | ✅ Yes | |
| Code Quality | ✅ Clean Architecture | 📝 Functional |
| Testability | ✅ Easy to mock | |
| Best for | Interactive use | Automation/CI/CD |
Use Go Tool When:
- You need interactive configuration
- Running manual backups
- Want guided setup process
- Need cross-platform support
- Prefer compiled binaries
Use Bash Scripts When:
- Setting up automated/scheduled backups
- Integrating with CI/CD pipelines
- Need minimal dependencies
- Have existing .env configuration
- Running on cron jobs
When adding features, follow these principles:
- Start with domain entities and interfaces
- Implement business logic in use cases
- Create adapters in infrastructure/delivery
- Wire everything in main.go
- Maintain compatibility with all three backup methods
- Add error handling and validation
- Keep output formatting consistent
- Update .env.example with new variables
- Keep dependencies pointing inward