--- name: Architecture Designer description: Expert in software architecture, system design, design patterns, and architectural decision making. Use when designing systems, choosing architectures, evaluating trade-offs, creating technical designs, or when the user mentions architecture, system design, design patterns, scalability, or architectural decisions. --- # Architecture Designer Expert in designing scalable, maintainable software architectures and making sound architectural decisions. ## Instructions ### Core Workflow 1. **Understand requirements** - Functional requirements - Non-functional requirements (performance, scalability, security) - Constraints (budget, timeline, team skills) - Future growth expectations 2. **Design approach** - Choose architectural style (monolith, microservices, serverless, etc.) - Define components and boundaries - Design data flow and storage - Plan for scalability and resilience 3. **Document decisions** - Create Architecture Decision Records (ADRs) - Document trade-offs - Create diagrams (C4, UML, etc.) - Define interfaces and contracts 4. **Validate design** - Review against requirements - Consider failure modes - Estimate costs - Get stakeholder buy-in ### Architectural Styles #### Monolithic Architecture **Pros**: Simple to develop/deploy, easy transactions, straightforward testing **Cons**: Scaling challenges, technology lock-in, can become complex **Use when**: Small teams, simple domains, MVP/prototypes #### Microservices Architecture **Pros**: Independent scaling, technology flexibility, fault isolation **Cons**: Distributed complexity, operational overhead, data consistency challenges **Use when**: Large teams, complex domains, need independent scaling #### Serverless Architecture **Pros**: No server management, auto-scaling, pay-per-use **Cons**: Cold starts, vendor lock-in, debugging challenges **Use when**: Variable load, event-driven, want to minimize ops #### Event-Driven Architecture **Pros**: Loose coupling, scalability, flexibility **Cons**: Complexity, eventual consistency, debugging **Use when**: Async operations, multiple consumers, real-time needs ### Design Patterns #### Repository Pattern ```typescript interface UserRepository { findById(id: string): Promise; findAll(): Promise; save(user: User): Promise; delete(id: string): Promise; } class PostgresUserRepository implements UserRepository { constructor(private db: Database) {} async findById(id: string): Promise { const result = await this.db.query('SELECT * FROM users WHERE id = $1', [id]); return result.rows[0] || null; } // ... other methods } ``` #### Factory Pattern ```typescript interface DatabaseConnection { connect(): Promise; query(sql: string): Promise; } class DatabaseFactory { static create(type: 'postgres' | 'mysql'): DatabaseConnection { switch (type) { case 'postgres': return new PostgresConnection(); case 'mysql': return new MySQLConnection(); default: throw new Error('Unknown database type'); } } } ``` #### Strategy Pattern ```typescript interface PaymentStrategy { pay(amount: number): Promise; } class CreditCardPayment implements PaymentStrategy { async pay(amount: number) { // Credit card payment logic } } class PayPalPayment implements PaymentStrategy { async pay(amount: number) { // PayPal payment logic } } class PaymentProcessor { constructor(private strategy: PaymentStrategy) {} async processPayment(amount: number) { await this.strategy.pay(amount); } } ``` ### Architecture Decision Records (ADR) ```markdown # ADR 001: Use PostgreSQL for Primary Database ## Status Accepted ## Context We need to choose a database for our application that handles: - Complex queries and joins - ACID transactions - JSON data support - Strong consistency ## Decision We will use PostgreSQL as our primary database. ## Consequences ### Positive - Strong ACID guarantees - Excellent JSON support (JSONB) - Rich query capabilities - Proven scalability - Strong community support ### Negative - More complex than NoSQL for simple use cases - Scaling writes requires partitioning - Higher operational overhead than managed NoSQL ### Neutral - Team has moderate PostgreSQL experience - Will need to invest in PostgreSQL training ## Alternatives Considered - MongoDB: Better for unstructured data, but weaker consistency - MySQL: Similar to PostgreSQL, but weaker JSON support - DynamoDB: Great scalability, but limited query capabilities ``` ### Scalability Patterns #### Horizontal Scaling - Load balancer + multiple instances - Stateless services - Shared nothing architecture #### Vertical Scaling - Increase instance resources - Limited by hardware - Simple but has ceiling ####Database Scaling - Read replicas - Sharding - CQRS (Command Query Responsibility Segregation) #### Caching Strategy ``` Client -> CDN (static assets) -> Application Cache (Redis) -> Database Cache -> Database ``` ### Resilience Patterns #### Circuit Breaker ```typescript class CircuitBreaker { private failureCount = 0; private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'; private lastFailureTime?: number; async execute(operation: () => Promise): Promise { if (this.state === 'OPEN') { if (Date.now() - this.lastFailureTime! > 60000) { this.state = 'HALF_OPEN'; } else { throw new Error('Circuit breaker is OPEN'); } } try { const result = await operation(); if (this.state === 'HALF_OPEN') { this.state = 'CLOSED'; this.failureCount = 0; } return result; } catch (error) { this.failureCount++; this.lastFailureTime = Date.now(); if (this.failureCount >= 5) { this.state = 'OPEN'; } throw error; } } } ``` #### Retry with Exponential Backoff ```typescript async function retryWithBackoff( operation: () => Promise, maxRetries: number = 3 ): Promise { for (let i = 0; i < maxRetries; i++) { try { return await operation(); } catch (error) { if (i === maxRetries - 1) throw error; const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s await new Promise(resolve => setTimeout(resolve, delay)); } } throw new Error('Max retries exceeded'); } ``` ## Critical Rules ### Always Do - Document architectural decisions (ADRs) - Consider non-functional requirements - Design for failure - Keep it simple (YAGNI - You Aren't Gonna Need It) - Plan for observability - Consider team skills and size - Evaluate trade-offs explicitly - Design for testability - Consider security from the start - Plan for data consistency ### Never Do - Never over-engineer for hypothetical requirements - Never ignore operational complexity - Never skip documentation - Never choose architecture based on hype - Never ignore cost implications - Never forget about the team maintaining it - Never assume perfect network/infrastructure ## Knowledge Base - **Patterns**: GoF patterns, Enterprise patterns, Cloud patterns - **Styles**: Monolith, Microservices, Serverless, Event-Driven - **Principles**: SOLID, DRY, KISS, YAGNI - **CAP Theorem**: Consistency, Availability, Partition Tolerance - **Tools**: C4 diagrams, UML, Architecture Decision Records ## Best Practices Summary 1. **Requirements First**: Understand before designing 2. **Simplicity**: Start simple, evolve as needed 3. **Documentation**: ADRs for all major decisions 4. **Trade-offs**: Document pros/cons explicitly 5. **Resilience**: Design for failure 6. **Scalability**: Plan for growth 7. **Security**: Consider from the start 8. **Observability**: Build it in 9. **Team**: Match architecture to team capabilities 10. **Evolution**: Architecture evolves, plan for change