Agent skill
System Boundaries
Defining clear boundaries between systems, services, and modules to manage complexity and enable independent evolution.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/system-boundaries-amnadtaowsoam-cerebratechai-claude-2
SKILL.md
System Boundaries
Overview
System Boundaries define where one system ends and another begins, establishing clear interfaces, ownership, and responsibilities. Well-defined boundaries reduce coupling and enable teams to work independently.
Core Principle: "Strong boundaries enable weak coupling. Define interfaces, not implementations."
1. Why System Boundaries Matter
- Reduces Coupling: Systems can evolve independently
- Enables Scaling: Teams can own and scale their systems
- Clarifies Ownership: Clear who is responsible for what
- Improves Testability: Easier to test in isolation
- Facilitates Understanding: Simpler mental models
2. Types of Boundaries
Service Boundaries
┌─────────────────┐ ┌─────────────────┐
│ User Service │────▶│ Order Service │
│ (owns users) │ │ (owns orders) │
└─────────────────┘ └─────────────────┘
│ │
▼ ▼
Users Table Orders Table
Module Boundaries (within monolith)
// src/modules/auth/
export interface AuthService {
login(credentials: Credentials): Promise<Token>;
verify(token: Token): Promise<User>;
}
// src/modules/orders/
import { AuthService } from '../auth'; // Uses interface, not implementation
Data Boundaries
Each service owns its own database:
- User Service → users_db
- Order Service → orders_db
- Payment Service → payments_db
No cross-database queries allowed!
3. Bounded Contexts (DDD)
## E-commerce System Boundaries
### Sales Context
- **Entities**: Product, Cart, Order
- **Language**: "Add to cart", "Checkout", "Purchase"
- **Owner**: Sales team
### Inventory Context
- **Entities**: Stock, Warehouse, SKU
- **Language**: "Restock", "Allocate", "Reserve"
- **Owner**: Operations team
### Shipping Context
- **Entities**: Shipment, Carrier, Tracking
- **Language**: "Ship", "Deliver", "Track"
- **Owner**: Logistics team
**Note**: "Product" means different things in each context!
- Sales: Product with price, description
- Inventory: Product with stock level, location
- Shipping: Product with weight, dimensions
4. Interface Definition
REST API Boundary
// Public API contract (boundary)
interface OrderAPI {
POST /orders
GET /orders/:id
PUT /orders/:id/cancel
}
// Implementation details (hidden)
class OrderService {
private database: Database;
private paymentGateway: PaymentGateway;
// Internal methods not exposed via API
private validateInventory() { }
private processPayment() { }
}
Event-Driven Boundary
// Published events (boundary)
interface OrderEvents {
'order.created': { orderId: string; userId: string; total: number };
'order.shipped': { orderId: string; trackingNumber: string };
}
// Other services subscribe to events, don't call directly
5. Ownership and Responsibilities
## Service Ownership Matrix
| Service | Team | Owns Data | Provides | Consumes |
|---------|------|-----------|----------|----------|
| User Service | Identity Team | Users, Profiles | User CRUD, Auth | - |
| Order Service | Commerce Team | Orders, Line Items | Order Management | User Service (user validation) |
| Payment Service | Finance Team | Transactions | Payment Processing | Order Service (order details) |
| Notification Service | Platform Team | - | Email/SMS | All services (events) |
6. Anti-Corruption Layer
// External API has different model than our domain
interface ExternalPaymentAPI {
charge(amount_cents: number, card_token: string): ExternalResponse;
}
// Anti-corruption layer translates
class PaymentAdapter {
constructor(private external: ExternalPaymentAPI) {}
async processPayment(payment: Payment): Promise<PaymentResult> {
// Translate our domain model to external API
const response = await this.external.charge(
payment.amount * 100, // dollars to cents
payment.cardToken
);
// Translate response back to our domain
return {
success: response.status === 'succeeded',
transactionId: response.id
};
}
}
7. Boundary Crossing Patterns
Synchronous (API Call)
// Order Service calls User Service
const user = await userService.getUser(userId);
if (!user) throw new Error('User not found');
Asynchronous (Events)
// Order Service publishes event
eventBus.publish('order.created', { orderId, userId, total });
// Notification Service subscribes
eventBus.subscribe('order.created', async (event) => {
await sendOrderConfirmationEmail(event.userId, event.orderId);
});
Shared Database (Anti-pattern)
// ❌ DON'T: Order Service directly queries users table
const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
// ✅ DO: Call User Service API
const user = await userService.getUser(userId);
8. Boundary Violations
Common Violations
// ❌ Violation: Reaching into another service's database
await orderDb.query('SELECT * FROM users WHERE id = ?', [userId]);
// ❌ Violation: Exposing internal implementation
class OrderService {
public database: Database; // Leaking internals
}
// ❌ Violation: Tight coupling
class OrderService {
constructor(private userService: UserServiceImpl) {} // Depends on concrete class
}
// ✅ Correct: Use interface
class OrderService {
constructor(private userService: IUserService) {} // Depends on interface
}
9. Boundary Testing
// Test boundary with mocks
describe('OrderService', () => {
it('validates user exists before creating order', async () => {
const mockUserService = {
getUser: jest.fn().mockResolvedValue(null)
};
const orderService = new OrderService(mockUserService);
await expect(
orderService.createOrder({ userId: '123', items: [] })
).rejects.toThrow('User not found');
expect(mockUserService.getUser).toHaveBeenCalledWith('123');
});
});
10. System Boundaries Checklist
- Clear Ownership: Each boundary has an owner?
- Well-Defined Interfaces: APIs/events documented?
- No Shared Databases: Each service owns its data?
- Bounded Contexts: Domain language consistent within boundary?
- Anti-Corruption Layers: External systems isolated?
- Testable: Can test each boundary independently?
- Documented: Boundaries documented in architecture diagrams?
- Enforced: Linting/architecture tests prevent violations?
Related Skills
59-architecture-decision/adr-templates40-system-resilience/service-mesh51-contracts-governance/api-contracts
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?