DEV Community

Syed Mehrab
Syed Mehrab

Posted on

Stop Leaking Your Database Logic: The Repository Pattern ๐Ÿ—๏ธ


Ever found yourself writing the same SQL query or ORM call in three different controllers? Or worseโ€”trying to unit test business logic but getting stuck because itโ€™s hard-coded to a live database?

Thatโ€™s where the Repository Pattern saves the day. It acts as a mediator between your domain/business logic and the data mapping layer.

The Architecture at a Glance
Instead of your service talking directly to the database, it talks to an Interface.

  • Client/Service: "I need user #42."

  • Repository: "I'll go get that for you (I don't care if it's from SQL, NoSQL, or a Cache)."

  • Data Source: Returns the raw data.

๐Ÿ’ป The "Before vs. After"
The "Spaghetti" Way (Logic + DB Mixed):

# Controller
def get_user_dashboard(user_id):
    user = db.query("SELECT * FROM users WHERE id = ?", user_id) # Leaking DB logic
    stats = redis.get(f"stats_{user_id}")
    return render_template(user=user, stats=stats)
Enter fullscreen mode Exit fullscreen mode

The Repository Way (Clean & Decoupled):

# Service
def get_user_dashboard(user_id):
    user = user_repo.get_by_id(user_id) # Abstracted
    stats = user_repo.get_activity_stats(user_id)
    return render_template(user=user, stats=stats)
Enter fullscreen mode Exit fullscreen mode

Why bother?

Testability: You can easily "mock" the repository during unit tests without needing a real database.

Don't Repeat Yourself (DRY): Centralize your data access logic. If a query needs to change, you change it in one place.

Flexibility: Want to switch from Postgres to MongoDB? You only update the Repository implementation; your business logic stays exactly the same.

Separation of Concerns: Your API/Controller stays "thin" and focused only on handling requests.

The "Golden Rule"
The Repository Pattern is powerful, but don't over-engineer! If you are building a very simple CRUD app with only 2-3 tables, adding a repository layer might just be unnecessary boilerplate.

Use it when your business logic starts getting complex or when you plan to support multiple data sources.

Top comments (0)