Implement Repository pattern for data access
✓Works with OpenClaudeYou are an architect designing a data-access layer using the Repository pattern. The user wants to implement a Repository pattern that abstracts data source operations behind a clean interface.
What to check first
- Identify all entities that need data access abstraction (User, Product, Order, etc.)
- Determine your data source: SQL database, NoSQL, REST API, or multiple sources
- Review existing ORM/query builder in use (TypeORM, Prisma, Sequelize, MongoDB driver, etc.)
Steps
- Define a base
IRepository<T>interface with CRUD operations:create(),findById(),findAll(),update(),delete() - Create a concrete repository class implementing
IRepository<T>for each entity (e.g.,UserRepository,ProductRepository) - In the repository constructor, inject the data source adapter (database connection, ORM session, API client)
- Implement each interface method to delegate actual queries to the injected adapter, never exposing the adapter details
- For complex queries, add custom methods to the repository like
findByEmail()orfindActiveUsers()without exposing query syntax - Create a Repository Factory or Service Locator to instantiate repositories and manage their lifecycle
- In your controllers/services, inject the repository interface—never the concrete implementation or raw data layer
- Test repositories by mocking the data source adapter, not the database itself
Code
// Base repository interface
interface IRepository<T> {
create(entity: T): Promise<T>;
findById(id: string): Promise<T | null>;
findAll(): Promise<T[]>;
update(id: string, entity: Partial<T>): Promise<T>;
delete(id: string): Promise<boolean>;
}
// Entity definition
interface User {
id: string;
email: string;
name: string;
createdAt: Date;
}
// Data source adapter (abstract the actual DB)
class DatabaseAdapter {
async query<T>(sql: string, params: any[]): Promise<T[]> {
// Raw database call (PostgreSQL, MySQL, etc.)
return [];
}
async execute(sql: string, params: any[]): Promise<any> {
// Insert/update/delete
return {};
}
}
// Concrete repository implementation
class UserRepository implements IRepository<User> {
constructor(private db: DatabaseAdapter) {}
async create(user: User): Promise<User> {
const sql = 'INSERT INTO users (id, email, name) VALUES ($1, $2, $3) RETURNING *';
const [result] = await this.db.query<User>(sql, [user.id, user.email, user.name]);
return result;
}
async findById(id: string): Promise<User | null> {
const sql = 'SELECT * FROM users WHERE id = $1';
const [user] = await
Note: this example was truncated in the source. See the GitHub repo for the latest full version.
Common Pitfalls
- Treating this skill as a one-shot solution — most workflows need iteration and verification
- Skipping the verification steps — you don't know it worked until you measure
- Applying this skill without understanding the underlying problem — read the related docs first
When NOT to Use This Skill
- When a simpler manual approach would take less than 10 minutes
- On critical production systems without testing in staging first
- When you don't have permission or authorization to make these changes
How to Verify It Worked
- Run the verification steps documented above
- Compare the output against your expected baseline
- Check logs for any warnings or errors — silent failures are the worst kind
Production Considerations
- Test in staging before deploying to production
- Have a rollback plan — every change should be reversible
- Monitor the affected systems for at least 24 hours after the change
Related Architecture Skills
Other Claude Code skills in the same category — free to download.
Singleton Pattern
Implement Singleton pattern
Factory Pattern
Implement Factory pattern
Observer Pattern
Implement Observer/PubSub pattern
Strategy Pattern
Implement Strategy pattern
Dependency Injection
Set up dependency injection
CQRS Setup
Implement CQRS pattern
Event Sourcing
Implement Event Sourcing pattern
Want a Architecture skill personalized to YOUR project?
This is a generic skill that works for everyone. Our AI can generate one tailored to your exact tech stack, naming conventions, folder structure, and coding patterns — with 3x more detail.