Framework Guide

DRY Up FastAPI GPT Dependency Hell

Centralises shared deps, cuts 1300 LoC, startup 3× faster.

January 15, 2025 6 min read

The problem

A fintech startup's FastAPI application took 45 seconds to start up and contained over 3,000 lines of duplicated dependency injection code. Every endpoint repeated the same database session, authentication, and service initialization logic. Adding a new feature required copying 50+ lines of boilerplate across multiple files. The test suite was unmaintainable with mock setups duplicated everywhere.

How AI created this issue

The team had asked ChatGPT to generate individual FastAPI endpoints. For each request, ChatGPT provided complete, self-contained code:


# ChatGPT generated endpoint 1
@app.post("/api/accounts")
async def create_account(
    request: AccountRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
    redis_client: Redis = Depends(get_redis),
    email_service: EmailService = Depends(get_email_service),
    audit_logger: AuditLogger = Depends(get_audit_logger),
    rate_limiter: RateLimiter = Depends(get_rate_limiter),
    feature_flags: FeatureFlags = Depends(get_feature_flags)
):
    # Endpoint logic...

# ChatGPT generated endpoint 2 (notice the repetition)
@app.get("/api/accounts/{account_id}")
async def get_account(
    account_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
    redis_client: Redis = Depends(get_redis),
    email_service: EmailService = Depends(get_email_service),
    audit_logger: AuditLogger = Depends(get_audit_logger),
    rate_limiter: RateLimiter = Depends(get_rate_limiter),
    feature_flags: FeatureFlags = Depends(get_feature_flags)
):
    # Endpoint logic...

# This pattern repeated 60+ times across the codebase!

ChatGPT treated each endpoint as an isolated example, never suggesting dependency composition or reuse patterns. The AI didn't recognize that repeating the same 7 dependencies across 60 endpoints was a maintenance nightmare waiting to happen.

The solution

  1. Created composable dependency classes: Consolidated common dependencies into reusable components:
    
    # Centralized dependency management
    class CommonDeps:
        def __init__(
            self,
            db: Session = Depends(get_db),
            current_user: User = Depends(get_current_user),
            redis: Redis = Depends(get_redis),
        ):
            self.db = db
            self.current_user = current_user
            self.redis = redis
    
    class ServiceDeps:
        def __init__(
            self,
            email: EmailService = Depends(get_email_service),
            audit: AuditLogger = Depends(get_audit_logger),
            limiter: RateLimiter = Depends(get_rate_limiter),
            flags: FeatureFlags = Depends(get_feature_flags)
        ):
            self.email = email
            self.audit = audit
            self.limiter = limiter
            self.flags = flags
    
    # Clean endpoint with composed dependencies
    @app.post("/api/accounts")
    async def create_account(
        request: AccountRequest,
        common: CommonDeps = Depends(),
        services: ServiceDeps = Depends()
    ):
        # Now access via common.db, services.email, etc.
  2. Implemented dependency caching: Added FastAPI's built-in caching to prevent recreating expensive resources
  3. Created domain-specific dependency groups: Built focused dependency sets for different API areas (auth, payments, reporting)
  4. Established dependency inheritance: Used class inheritance for specialized dependency variations
  5. Automated dependency documentation: Generated OpenAPI docs showing dependency relationships

The results

  • Reduced codebase by 1,300 lines (40% reduction in boilerplate)
  • Startup time dropped from 45s to 12s (3.75x faster)
  • Test setup simplified by 80% - mock once, reuse everywhere
  • New endpoint development time cut by 65%
  • Memory usage reduced by 200MB through proper dependency caching
  • Zero dependency-related bugs in 6 months (down from 2-3 per sprint)

The team learned that AI-generated code often lacks architectural vision. While ChatGPT excels at generating working endpoints, it doesn't consider the bigger picture of maintainability, DRY principles, or performance at scale. They now use AI for implementation details but design the architecture themselves.

Ready to fix your codebase?

Let us analyze your application and resolve these issues before they impact your users.

Get Diagnostic Assessment →