A simple database query that normally runs in under 0.1 seconds was suddenly taking 3 seconds. No schema changes. No new joins. No suspicious filters. Just a plain, boring query that had decided to become slow.

So we started digging.

Finding the Real Problem

One of the first things we checked was the number of active connections to the database. That’s when we saw it. One of our applications had more than 20 active connections open at the same time. Just for that single app.

Out of curiosity, we terminated the application and reran the exact same query. It completed in less than a tenth of a second.

The query was never slow. The Oracle database was under unnecessary pressure because of how our application was managing its connections. Or rather, mismanaging them.

The Culprit: One Connection Per Object

Looking into the code, we found the issue. Every time a certain part of the application needed to talk to the database, it created its own connection object.

Different parts of the code were doing:

  • new Database() here
  • new Database() there
  • Then holding on to those connections longer than necessary

None of this looked horrible at a glance. But in practice, the database was juggling dozens of concurrent connections from a single application that didn’t need them.

The Fix: A Simple Singleton

The solution was textbook. We changed the database access logic so the application used a singleton object for its connection.

That meant:

  • The application maintained only one active connection
  • All code that needed the database shared the same instance
  • We stopped flooding Oracle with unnecessary connections

After that change, query times went back to normal and stayed there.

What the Code Looked Like

Before: Creating New Connections Everywhere

Every time the constructor runs, a new Oracle connection opens:

java

public class BadOracleDatabase {
    private Connection connection;

    public BadOracleDatabase() throws SQLException {
        // New connection every time this is called
        this.connection = DriverManager.getConnection(
            "jdbc:oracle:thin:@//db.mycompany.com:1521/ORCLEDB",
            "<app_user>",
            "<secret>"
        );
    }

    public Connection getConnection() {
        return connection;
    }
}

When different classes keep calling new BadOracleDatabase(), you end up with dozens of open connections. That’s when the database starts choking.

After: One Shared Instance

The Singleton version ensures the application shares a single connection:

java

public class OracleDatabase {
    private static OracleDatabase instance;
    private Connection connection;

    private OracleDatabase() throws SQLException {
        this.connection = DriverManager.getConnection(
            "jdbc:oracle:thin:@//db.mycompany.com:1521/ORCLEDB",
            "<app_user>",
            "<secret>"
        );
    }

    public static synchronized OracleDatabase getInstance() throws SQLException {
        if (instance == null || instance.getConnection() == null || 
            instance.getConnection().isClosed()) {
            instance = new OracleDatabase();
        }
        return instance;
    }

    public Connection getConnection() {
        return connection;
    }
}

Now all database-using code goes through OracleDatabase.getInstance() instead of creating new objects. One shared instance. One active connection. Problem solved.

Why This Matters Beyond the Code

This wasn’t a fancy microservice refactor or a massive infrastructure overhaul. It was a basic design pattern that most developers learn early and then forget to apply.

But that small change:

  • Improved query performance by orders of magnitude
  • Reduced database load significantly
  • Made the system more predictable under normal operations
  • Saved hours of debugging and tuning
  • Avoided unnecessary scaling costs

The broader lesson is simple. You don’t always need something exotic to solve real problems. Sometimes, recognizing that something should be a shared object instead of N separate ones is enough.

Design patterns aren’t academic exercises. They’re practical tools that save time, money, and headaches. This one certainly did for us.