Database Backed Singleton Design Pattern for Distributed Systems

What is a Database-Backed Singleton Design Pattern?

A Database-Backed Singleton is a Singleton implementation where the instance is stored and retrieved from a database instead of being kept in memory. This ensures the Singleton remains consistent across multiple JVMs in a distributed system.

Why Use a Database-Backed Singleton?

  1. Ensures Consistency Across Multiple JVMs – Unlike traditional in-memory Singletons, this pattern ensures a single instance is shared across multiple server instances.
  2. Persists Singleton Data – This is useful for configurations, counters, or unique identifiers that should persist even after application restarts.
  3. Avoids Memory Overhead – Traditional Singleton stays in memory, but this approach loads data only when required.

Advantages of Database-Backed Singleton

  • Works in Multi-JVM Environments – Unlike traditional Singleton, this works across multiple instances of an application.
  • Persistence – Data is not lost when the application restarts.
  • Centralized Management – Singleton data can be updated dynamically.

Disadvantages of Database-Backed Singleton

  • Database Overhead – Querying the database for every instance lookup adds latency.
  • Single Point of Failure – If the database goes down, the Singleton cannot be retrieved.
  • Complexity – More complex than an in-memory Singleton.

Use Cases of Database-Backed Singleton

  • Global Configuration Settings – Store configuration settings in the database.
  • Feature Flags – Enable/disable features dynamically without restarting the application.
  • Application Licensing – Manage licensing keys for applications.
  • Distributed Locking – Used in distributed systems to ensure only one instance modifies critical data.

Brief Description of Implementation

I have developed a small program to understand the Database-backed Singleton Design Pattern by creating a table named singleton_instance in MySQL and required Java code to support the type of Singleton Design Pattern.

In 1st Step, I created a table named singleton_instance in MySQL Database having 2 columns named id and instance_data.

CREATE TABLE singleton_instance (
    id SERIAL PRIMARY KEY,
    instance_data TEXT NOT NULL
);

2nd Step, I have developed the code for the Database Backed Singleton Design in the class named DatabaseSingleton.java

public class DatabaseSingleton {
	
	private static final Logger LOG = LoggerFactory.getLogger(DatabaseSingleton.class);
	
	private static DatabaseSingleton instance;
	
	private static final String DB_URL = "jdbc:mysql://localhost:3306/spring";
	private static final String DB_USERNAME = "root";
	private static final String DB_PASSWORD = "root";
	
	private String instanceData;
	
	private DatabaseSingleton(String instanceData) {
		this.instanceData = instanceData;
	}
	
	public static DatabaseSingleton getInstance() {
		if(null == instance) {
			try(Connection connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
					PreparedStatement preparedStatement = connection.prepareStatement("SELECT instance_data FROM singleton_instance LIMIT 1");
					ResultSet resultSet = preparedStatement.executeQuery()) {
				if(resultSet.next()) {
					synchronized (DatabaseSingleton.class) {
						instance = new DatabaseSingleton(resultSet.getString("instance_data"));
					}
				} else {
					String defaultData = "Database Driven Singleton in Distributed Systems.";
					synchronized (DatabaseSingleton.class) {
						try(PreparedStatement statement = connection.
								prepareStatement("INSERT INTO singleton_instance (instance_data) VALUES (?)")) {
							statement.setString(1, defaultData);
							statement.executeUpdate();
						}
						instance = new DatabaseSingleton(defaultData);
					}
				}
			} catch(Exception e) {
				LOG.error("Exception occurred : {}", e);
			}
		}
		return instance;
	}
	
	public String getInstanceData() {
		return instanceData;
	}
	
	public void updateInstanceData(String newData) {
		this.instanceData = newData;
		
		try(Connection connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
				PreparedStatement preparedStatement = connection.prepareStatement("UPDATE singleton_instance SET instance_data = ? WHERE id = 1")) {
			preparedStatement.setString(1, newData);
			preparedStatement.executeUpdate();
		} catch (Exception e) {
			LOG.error("Exception occurred while updating the Data : {}", e);
		}
	}
}

In the 3rd Step, I created a main class named DatabaseBackedSingletonMasterclassApplication.java to test the Database Backed Singleton Design Pattern concept.

public class DatabaseBackedSingletonMasterclassApplication {
	
	private static final Logger LOG = LoggerFactory.getLogger(DatabaseBackedSingletonMasterclassApplication.class);

	public static void main(String[] args) {
		DatabaseSingleton singleton = DatabaseSingleton.getInstance();
        LOG.info("Initial Data: {}", singleton.getInstanceData());
        // Update Singleton instance data
        singleton.updateInstanceData("Updated Singleton Data in Distributed Systems.");
        // Fetch instance again to check if data is updated
        DatabaseSingleton singleton2 = DatabaseSingleton.getInstance();
        LOG.info("Updated Data: {}", singleton2.getInstanceData());
	}
}

I have provided the log to understand how it is working.

INFO com.springcavaj.designpattern.singleton.database.DatabaseBackedSingletonMasterclassApplication - Initial Data: Database Driven Singleton in Distributed Systems.

INFO com.springcavaj.designpattern.singleton.database.DatabaseBackedSingletonMasterclassApplication - Updated Data: Updated Singleton Data in Distributed Systems.

Steps to run the application

The complete Run application steps are provided in this README.md file, but still, I am providing the steps to run points below.

  • Download MySQL
  • Install MySQL on local machine
  • Run the MySQL Server
  • Execute the script as provided in the repository create_table.sql
  • Clone the sprincavaj-designpattern application from the GitHub repository.
  • Import the application as a Maven application, either in STS or Eclipse.
  • Find the DatabaseBackedSingletonMasterclassApplication.java class.
  • Right-click on the file and select Run As -> Java Application.

GitHub Code Link

Download the Source Code from GitHub