Skip to content

How to Backup H2 Database While It's Running

Problem

I needed to back up my H2 database in a production environment, but shutting down the application wasn’t an option. The database runs in embedded mode as part of a Java application that needs to stay online 24/7.

At first, I thought about copying the database files directly. But I quickly realized this approach is risky—copying files while the database is running could result in inconsistent or corrupted backups because the database might be in the middle of a write operation.

I searched for a way to create consistent backups without stopping my application.

Purpose

I wanted to find a method to create reliable backups of H2 database while it continues to run and serve requests. The backup needed to be consistent—capturing a snapshot of the database at a specific point in time without any partial writes or corruption.

Solution

I found that H2 provides a built-in BACKUP TO SQL command that creates a consistent ZIP archive snapshot of the database. This command runs through a normal database connection, so the H2 engine handles all the consistency concerns internally.

Basic JDBC Approach

Here’s how I implemented it using plain JDBC:

BackupManager.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class BackupManager {
public void createBackup(String dbPath, String user, String password) throws Exception {
// Generate timestamped backup filename
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"));
String backupFile = "backup-" + timestamp + ".zip";
try (Connection con = DriverManager.getConnection(
"jdbc:h2:" + dbPath, user, password);
PreparedStatement ps = con.prepareStatement(
"BACKUP TO '" + backupFile + "'")) {
ps.executeUpdate();
System.out.println("Backup created: " + backupFile);
}
}
}

The key insight is that BACKUP TO is just a regular SQL command. You execute it the same way you would execute any other SQL statement. The H2 engine ensures the backup is consistent by coordinating with its internal state.

Spring Data Integration

Since my application uses Spring Data, I also tried a native query approach:

H2BackupRepository.java
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
public interface H2BackupRepository extends JpaRepository<Object, Long> {
@Modifying
@Transactional
@Query(value = "BACKUP TO '/backups/h2-backup.zip'", nativeQuery = true)
void createBackup();
}

This approach works well when backup logic needs to stay close to your application code.

Scheduled Backups

I also set up scheduled backups using Spring’s scheduling:

ScheduledBackupService.java
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class ScheduledBackupService {
private final H2BackupRepository backupRepository;
public ScheduledBackupService(H2BackupRepository backupRepository) {
this.backupRepository = backupRepository;
}
@Scheduled(cron = "0 0 2 * * ?") // Daily at 2 AM
public void performDailyBackup() {
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"));
String backupPath = "/backups/h2-" + timestamp + ".zip";
backupRepository.createBackup();
}
}

What I Learned

Don’t copy database files directly. While the database is running, the file contents might be in an inconsistent state. The BACKUP TO command solves this by having the database engine coordinate the backup process.

No downtime required. The database continues to accept reads and writes during the backup. H2 handles the consistency internally.

Simple integration. Since it’s just a SQL command, you can use it with any framework that supports native queries—no special backup tools needed.

Common Mistakes to Avoid

  1. Copying .db files while database runs - This can result in corrupted backups
  2. Assuming you need to shut down - H2 supports online backups out of the box
  3. Not backing up at all - Even small databases need regular backups

Summary

H2’s BACKUP TO command lets you create consistent backups without stopping your database. You run it as a regular SQL command through JDBC or Spring Data, and H2 handles the consistency for you. This approach works well for production applications that need continuous availability with reliable backup capability.

The command creates a ZIP archive containing a snapshot of your database at the moment the backup starts. You can then store this archive wherever you keep your backups—cloud storage, network drives, or local backup systems.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments