Skip to main content

Singleton Pattern in FastAPI Dependency Injection

ยท 5 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. In web development, this is essential for managing resources like database pools, configuration objects, logging handlers, or complex machine learning models that are costly to initialize.

In FastAPI, while dependencies are generally executed once per request and the result is cached, this does not guarantee that the underlying class is instantiated only once across the entire application's lifecycle. To enforce a true global Singleton, we must use Python's built-in methods, typically overriding __new__.

1. Defining the Singleton Classโ€‹

We implement the Singleton logic within the class itself by overriding the __new__ method. This ensures that the initialization code runs only once when the application starts.

import time
from fastapi import FastAPI, Depends
from typing import Annotated

# --- 1. The Singleton Implementation ---
class GlobalConfigService:
"""
A service that guarantees only one instance exists across the application.
The initialization logic runs only once.
"""
_instance = None

def __new__(cls):
# Check if the instance already exists
if cls._instance is None:
print("[INFO] Singleton initializing... (Expensive initialization)")

# --- Simulation of one-time setup ---
cls._start_time = time.time()
cls._version = "v2.1"
# ------------------------------------

# Create the instance only if it doesn't exist
cls._instance = super(GlobalConfigService, cls).__new__(cls)

# Always return the single existing instance
return cls._instance

def get_uptime(self):
return time.time() - self._start_time

def get_version(self):
return self._version

def __call__(self):
"""
The __call__ method allows the class to be used directly in Depends().
It returns the instance itself.
"""
return self._instance

# --- 2. FastAPI Application Setup ---
app = FastAPI()

# Define the dependency type hint
Singleton = Annotated[GlobalConfigService, Depends(GlobalConfigService)]

Annotation: By overriding __new__, we control the instantiation process. The heavy initialization logic runs only on the first call to GlobalConfigService(), ensuring that subsequent calls immediately return the single, cached _instance.


2. Injecting the Singleton into Routesโ€‹

We inject the class directly into the route using Depends(GlobalConfigService).

A. Simple Injectionโ€‹

The first request to any of these endpoints will trigger the __new__ method, printing "Singleton initializing..." only once in the lifetime of the FastAPI process.

@app.get("/version")
def get_version_info(config: Singleton):
"""
Injects the single instance of GlobalConfigService.
"""
return {
"api_version": config.get_version(),
"instance_id": id(config) # Used to verify the same instance is returned
}

@app.get("/uptime")
def get_uptime_info(config: Singleton):
"""
Subsequent requests reuse the same instance. The initialization is not rerun.
"""
return {
"version": config.get_version(),
"uptime_seconds": config.get_uptime()
}

# Annotation: When FastAPI calls GlobalConfigService() via Depends(), Python's
# internal __new__ method intercepts the creation, guaranteeing that both
# '/version' and '/uptime' always receive the exact same object in memory.

3. Why this Method Works Bestโ€‹

MethodInstantiation FrequencyUse Case
Simple Function Dependency (def get_db(): return DB())Once Per RequestDatabase sessions, request-scoped data.
yield Dependency (def get_db(): yield DB())Once Per RequestDatabase sessions with guaranteed teardown.
Class with __new__ (Singleton)Once Per Application LifecycleGlobal configuration, costly service initialization (e.g., ML models, logging).

By using the __new__ method, you ensure that the creation overhead is incurred only once when the server starts, making the service globally efficient and safe for managing shared state.


Sources and Further Readingโ€‹

  1. Python Documentation - Customizing class creation (__new__)
  2. FastAPI Documentation - Classes as Dependencies
  3. Stack Overflow - Python Singleton implementation