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()herenew 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.



