Chapter 14 System Architecture and Design Patterns - Bryantad/Sona GitHub Wiki
Chapter 14: System Architecture and Design Patterns
Building Large-Scale, Maintainable Applications: Architecture Patterns for the Real World
Andre's Architecture Philosophy
"Great software architecture isn't about using the most complex patterns or the latest frameworksβit's about solving real problems with clarity and purpose. Over the years building Sona and various applications, I've learned that the best architectures are those that grow naturally with your needs, remain understandable to your team, and can adapt to changing requirements. This chapter will teach you to think like a software architect."
The Architecture Evolution Path
System Complexity vs Architecture Needs
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Simple Script β
β β β
β Single Application β
β β β
β Modular Application β
β β β
β Distributed System β
β β β
β Microservices Architecture β
β β β
β Event-Driven Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Learning Objectives
By the end of this chapter, you will:
- Design scalable application architectures using proven patterns
- Implement Domain-Driven Design (DDD) principles in Sona
- Build event-driven systems with reliable messaging
- Create clean, maintainable code using SOLID principles
- Design APIs that can evolve without breaking clients
- Implement monitoring, logging, and observability patterns
- Handle system failures gracefully with resilience patterns
- Build security into your architecture from the ground up
Section 1: Layered Architecture and Domain-Driven Design
Building a Clean Architecture Foundation
// Clean Architecture implementation in Sona
// Domain Layer - Core business logic, no external dependencies
class User {
id: string
email: string
username: string
created_at: datetime
is_active: bool
constructor(id, email, username) {
self.id = id
self.email = email
self.username = username
self.created_at = datetime.now()
self.is_active = true
self.validate()
}
validate() {
if not self.email or not self.email.contains("@") {
throw InvalidEmailError("Email must be valid")
}
if not self.username or self.username.length < 3 {
throw InvalidUsernameError("Username must be at least 3 characters")
}
}
activate() {
self.is_active = true
return UserActivatedEvent(self.id, datetime.now())
}
deactivate() {
self.is_active = false
return UserDeactivatedEvent(self.id, datetime.now())
}
change_email(new_email) {
let old_email = self.email
self.email = new_email
self.validate()
return EmailChangedEvent(self.id, old_email, new_email, datetime.now())
}
}
// Domain Services - Complex business logic that doesn't belong to entities
class UserDomainService {
user_repository: UserRepository
constructor(user_repository) {
self.user_repository = user_repository
}
async is_username_unique(username, excluding_user_id = null) {
let existing_user = await self.user_repository.find_by_username(username)
if not existing_user {
return true
}
return excluding_user_id and existing_user.id == excluding_user_id
}
async calculate_user_metrics(user_id) {
let user = await self.user_repository.find_by_id(user_id)
if not user {
throw UserNotFoundError(f"User {user_id} not found")
}
// Complex domain logic for calculating user metrics
let account_age_days = (datetime.now() - user.created_at).days
let activity_score = await self.calculate_activity_score(user)
let engagement_level = self.classify_engagement_level(activity_score, account_age_days)
return UserMetrics(
user_id: user.id,
account_age_days: account_age_days,
activity_score: activity_score,
engagement_level: engagement_level
)
}
async calculate_activity_score(user) {
// Domain-specific calculation logic
// This would integrate with other domain services
return 85.5 // Simplified for example
}
classify_engagement_level(activity_score, account_age_days) {
if activity_score > 80 and account_age_days > 30 {
return "HIGHLY_ENGAGED"
} elif activity_score > 50 {
return "MODERATELY_ENGAGED"
} else {
return "LOW_ENGAGEMENT"
}
}
}
// Application Layer - Use cases and application services
class CreateUserUseCase {
user_repository: UserRepository
user_domain_service: UserDomainService
event_dispatcher: EventDispatcher
constructor(user_repository, user_domain_service, event_dispatcher) {
self.user_repository = user_repository
self.user_domain_service = user_domain_service
self.event_dispatcher = event_dispatcher
}
async execute(command) {
// Validate command
self.validate_command(command)
// Check business rules
let is_username_unique = await self.user_domain_service.is_username_unique(command.username)
if not is_username_unique {
throw UsernameAlreadyExistsError(f"Username '{command.username}' is already taken")
}
// Create domain entity
let user = User(
id: generate_user_id(),
email: command.email,
username: command.username
)
// Persist entity
await self.user_repository.save(user)
// Dispatch domain events
let user_created_event = UserCreatedEvent(
user_id: user.id,
email: user.email,
username: user.username,
occurred_at: datetime.now()
)
await self.event_dispatcher.dispatch(user_created_event)
return CreateUserResult(
user_id: user.id,
success: true,
message: "User created successfully"
)
}
validate_command(command) {
if not command.email {
throw ValidationError("Email is required")
}
if not command.username {
throw ValidationError("Username is required")
}
if command.password and command.password.length < 8 {
throw ValidationError("Password must be at least 8 characters")
}
}
}
// Infrastructure Layer - External concerns (databases, APIs, etc.)
class PostgreSQLUserRepository implements UserRepository {
database: Database
constructor(database) {
self.database = database
}
async save(user) {
let query = """
INSERT INTO users (id, email, username, created_at, is_active)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (id) DO UPDATE SET
email = EXCLUDED.email,
username = EXCLUDED.username,
is_active = EXCLUDED.is_active
"""
await self.database.execute(query, [
user.id,
user.email,
user.username,
user.created_at,
user.is_active
])
}
async find_by_id(user_id) {
let query = "SELECT * FROM users WHERE id = $1"
let result = await self.database.query_one(query, [user_id])
if not result {
return null
}
return self.map_to_domain_entity(result)
}
async find_by_username(username) {
let query = "SELECT * FROM users WHERE username = $1"
let result = await self.database.query_one(query, [username])
if not result {
return null
}
return self.map_to_domain_entity(result)
}
map_to_domain_entity(row) {
let user = User(row.id, row.email, row.username)
user.created_at = row.created_at
user.is_active = row.is_active
return user
}
}
// Presentation Layer - Controllers and API endpoints
class UserController {
create_user_use_case: CreateUserUseCase
get_user_use_case: GetUserUseCase
constructor(create_user_use_case, get_user_use_case) {
self.create_user_use_case = create_user_use_case
self.get_user_use_case = get_user_use_case
}
async create_user(request) {
try {
let command = CreateUserCommand(
email: request.body.email,
username: request.body.username,
password: request.body.password
)
let result = await self.create_user_use_case.execute(command)
return {
"status": 201,
"body": {
"success": true,
"user_id": result.user_id,
"message": result.message
}
}
} catch (ValidationError as e) {
return {
"status": 400,
"body": {
"success": false,
"error": "VALIDATION_ERROR",
"message": e.message
}
}
} catch (UsernameAlreadyExistsError as e) {
return {
"status": 409,
"body": {
"success": false,
"error": "USERNAME_EXISTS",
"message": e.message
}
}
} catch (error) {
log_error("user_creation_failed", {
"error": error.message,
"request_id": request.id
})
return {
"status": 500,
"body": {
"success": false,
"error": "INTERNAL_ERROR",
"message": "An unexpected error occurred"
}
}
}
}
async get_user(request) {
try {
let user_id = request.params.user_id
let query = GetUserQuery(user_id: user_id)
let result = await self.get_user_use_case.execute(query)
return {
"status": 200,
"body": {
"user": {
"id": result.user.id,
"email": result.user.email,
"username": result.user.username,
"created_at": result.user.created_at.iso_string(),
"is_active": result.user.is_active
}
}
}
} catch (UserNotFoundError) {
return {
"status": 404,
"body": {
"success": false,
"error": "USER_NOT_FOUND",
"message": "User not found"
}
}
}
}
}
Section 2: Event-Driven Architecture
Building Robust Event Systems
// Event-driven architecture implementation
abstract class DomainEvent {
event_id: string
occurred_at: datetime
version: int
constructor() {
self.event_id = generate_event_id()
self.occurred_at = datetime.now()
self.version = 1
}
abstract get_event_type(): string
abstract to_dict(): {}
}
class UserCreatedEvent extends DomainEvent {
user_id: string
email: string
username: string
constructor(user_id, email, username) {
super()
self.user_id = user_id
self.email = email
self.username = username
}
get_event_type() {
return "USER_CREATED"
}
to_dict() {
return {
"event_id": self.event_id,
"event_type": self.get_event_type(),
"occurred_at": self.occurred_at.iso_string(),
"version": self.version,
"data": {
"user_id": self.user_id,
"email": self.email,
"username": self.username
}
}
}
}
// Event Store for persistence and replay
class EventStore {
database: Database
constructor(database) {
self.database = database
}
async save_event(event) {
let query = """
INSERT INTO events (event_id, event_type, aggregate_id, data, occurred_at, version)
VALUES ($1, $2, $3, $4, $5, $6)
"""
let aggregate_id = self.extract_aggregate_id(event)
await self.database.execute(query, [
event.event_id,
event.get_event_type(),
aggregate_id,
json.stringify(event.to_dict()),
event.occurred_at,
event.version
])
}
async get_events_for_aggregate(aggregate_id, from_version = 0) {
let query = """
SELECT * FROM events
WHERE aggregate_id = $1 AND version > $2
ORDER BY version ASC
"""
let rows = await self.database.query(query, [aggregate_id, from_version])
return rows.map(row => self.deserialize_event(row))
}
async get_all_events(from_timestamp = null, limit = 1000) {
let query = """
SELECT * FROM events
WHERE ($1 IS NULL OR occurred_at > $1)
ORDER BY occurred_at ASC
LIMIT $2
"""
let rows = await self.database.query(query, [from_timestamp, limit])
return rows.map(row => self.deserialize_event(row))
}
extract_aggregate_id(event) {
// Extract the main entity ID from the event
if hasattr(event, "user_id") {
return event.user_id
} elif hasattr(event, "order_id") {
return event.order_id
} else {
return event.event_id // Fallback
}
}
deserialize_event(row) {
let event_data = json.parse(row.data)
// Factory pattern to recreate events
match row.event_type {
"USER_CREATED" => {
let event = UserCreatedEvent(
event_data.data.user_id,
event_data.data.email,
event_data.data.username
)
event.event_id = event_data.event_id
event.occurred_at = datetime.parse(event_data.occurred_at)
return event
},
default => {
throw UnknownEventTypeError(f"Unknown event type: {row.event_type}")
}
}
}
}
// Event Dispatcher with reliable delivery
class EventDispatcher {
handlers: {}
event_store: EventStore
message_queue: MessageQueue
retry_policy: RetryPolicy
constructor(event_store, message_queue) {
self.handlers = {}
self.event_store = event_store
self.message_queue = message_queue
self.retry_policy = ExponentialBackoffRetryPolicy(
max_retries: 5,
base_delay: 1.0,
max_delay: 60.0
)
}
register_handler(event_type, handler) {
if event_type not in self.handlers {
self.handlers[event_type] = []
}
self.handlers[event_type].append(handler)
print(f"Registered handler for {event_type}: {handler.name}")
}
async dispatch(event) {
// Save event first for durability
await self.event_store.save_event(event)
// Dispatch to local handlers
await self.dispatch_locally(event)
// Publish to message queue for remote handlers
await self.publish_to_queue(event)
}
async dispatch_locally(event) {
let event_type = event.get_event_type()
if event_type not in self.handlers {
return // No handlers registered
}
let handlers = self.handlers[event_type]
# Dispatch to all handlers concurrently
let handler_tasks = []
for handler in handlers {
let task = self.execute_handler_with_retry(handler, event)
handler_tasks.append(task)
}
# Wait for all handlers to complete
let results = await gather_with_exceptions(handler_tasks)
# Log any handler failures
for i, result in enumerate(results) {
if result.is_error {
log_error("event_handler_failed", {
"event_id": event.event_id,
"event_type": event_type,
"handler": handlers[i].name,
"error": result.error.message
})
}
}
}
async execute_handler_with_retry(handler, event) {
let attempt = 0
let last_error = null
while attempt < self.retry_policy.max_retries {
try {
await handler.handle(event)
return # Success
} catch (error) {
last_error = error
attempt += 1
if attempt < self.retry_policy.max_retries {
let delay = self.retry_policy.calculate_delay(attempt)
print(f"Handler {handler.name} failed (attempt {attempt}), retrying in {delay}s")
await sleep(delay)
}
}
}
# All retries exhausted
throw HandlerRetryExhaustedError(
f"Handler {handler.name} failed after {attempt} attempts: {last_error.message}"
)
}
async publish_to_queue(event) {
let message = {
"event_id": event.event_id,
"event_type": event.get_event_type(),
"event_data": event.to_dict(),
"published_at": datetime.now().iso_string()
}
await self.message_queue.publish(
topic: "domain_events",
message: message,
routing_key: event.get_event_type()
)
}
}
// Event Handlers
class SendWelcomeEmailHandler {
email_service: EmailService
constructor(email_service) {
self.email_service = email_service
self.name = "SendWelcomeEmailHandler"
}
async handle(event) {
if not isinstance(event, UserCreatedEvent) {
return # Not interested in this event
}
print(f"Sending welcome email to {event.email}")
await self.email_service.send_email(
to: event.email,
subject: f"Welcome {event.username}!",
template: "welcome_email",
variables: {
"username": event.username,
"user_id": event.user_id
}
)
print(f"Welcome email sent successfully to {event.email}")
}
}
class UserAnalyticsHandler {
analytics_service: AnalyticsService
constructor(analytics_service) {
self.analytics_service = analytics_service
self.name = "UserAnalyticsHandler"
}
async handle(event) {
if not isinstance(event, UserCreatedEvent) {
return
}
await self.analytics_service.track_event(
event_name: "user_registered",
user_id: event.user_id,
properties: {
"email_domain": event.email.split("@")[1],
"username_length": event.username.length,
"registration_timestamp": event.occurred_at.iso_string()
}
)
print(f"User registration tracked in analytics: {event.user_id}")
}
}
Section 3: Microservices Architecture Patterns
Service Mesh and Communication Patterns
// Service registry and discovery
class ServiceRegistry {
services: {}
health_checker: HealthChecker
load_balancer: LoadBalancer
constructor() {
self.services = {}
self.health_checker = HealthChecker()
self.load_balancer = RoundRobinLoadBalancer()
}
register_service(service_name, instance) {
if service_name not in self.services {
self.services[service_name] = []
}
let service_instance = ServiceInstance(
id: generate_instance_id(),
name: service_name,
host: instance.host,
port: instance.port,
metadata: instance.metadata or {},
health_check_url: instance.health_check_url,
registration_time: datetime.now()
)
self.services[service_name].append(service_instance)
# Start health checking for this instance
self.health_checker.start_monitoring(service_instance)
print(f"Registered service instance: {service_name}@{instance.host}:{instance.port}")
}
discover_service(service_name) {
if service_name not in self.services {
throw ServiceNotFoundError(f"Service '{service_name}' not registered")
}
let healthy_instances = self.services[service_name].filter(
instance => instance.status == "HEALTHY"
)
if healthy_instances.length == 0 {
throw NoHealthyInstancesError(f"No healthy instances for service '{service_name}'")
}
return self.load_balancer.select_instance(healthy_instances)
}
deregister_service(service_name, instance_id) {
if service_name in self.services {
self.services[service_name] = self.services[service_name].filter(
instance => instance.id != instance_id
)
self.health_checker.stop_monitoring(instance_id)
print(f"Deregistered service instance: {instance_id}")
}
}
}
// API Gateway pattern
class APIGateway {
service_registry: ServiceRegistry
rate_limiter: RateLimiter
auth_service: AuthService
circuit_breakers: {}
constructor(service_registry, auth_service) {
self.service_registry = service_registry
self.auth_service = auth_service
self.rate_limiter = RateLimiter()
self.circuit_breakers = {}
self.setup_routes()
}
setup_routes() {
# Route configuration with service mapping
self.routes = {
"/api/users/*": {
"service": "user-service",
"strip_prefix": "/api/users",
"auth_required": true,
"rate_limit": "100/minute"
},
"/api/orders/*": {
"service": "order-service",
"strip_prefix": "/api/orders",
"auth_required": true,
"rate_limit": "50/minute"
},
"/api/public/*": {
"service": "public-api-service",
"strip_prefix": "/api/public",
"auth_required": false,
"rate_limit": "1000/minute"
}
}
}
async handle_request(request) {
try {
# Route matching
let route_config = self.match_route(request.path)
if not route_config {
return self.create_error_response(404, "Route not found")
}
# Authentication
if route_config.auth_required {
let auth_result = await self.auth_service.authenticate(request)
if not auth_result.success {
return self.create_error_response(401, "Authentication required")
}
request.user = auth_result.user
}
# Rate limiting
let rate_limit_result = await self.rate_limiter.check_limit(
request.client_ip,
route_config.rate_limit
)
if not rate_limit_result.allowed {
return self.create_error_response(
429,
"Rate limit exceeded",
headers: {
"X-RateLimit-Reset": rate_limit_result.reset_time
}
)
}
# Service discovery and routing
let target_service = route_config.service
let service_instance = self.service_registry.discover_service(target_service)
# Circuit breaker pattern
let circuit_breaker = self.get_circuit_breaker(target_service)
let response = await circuit_breaker.execute(async func() {
return await self.forward_request(request, service_instance, route_config)
})
return response
} catch (error) {
log_error("api_gateway_error", {
"path": request.path,
"method": request.method,
"error": error.message,
"request_id": request.id
})
return self.create_error_response(500, "Internal server error")
}
}
match_route(path) {
for route_pattern in self.routes {
if self.path_matches_pattern(path, route_pattern) {
return self.routes[route_pattern]
}
}
return null
}
path_matches_pattern(path, pattern) {
# Simple glob-style matching
if pattern.endswith("/*") {
let prefix = pattern[:-2] # Remove /*
return path.startswith(prefix)
}
return path == pattern
}
async forward_request(request, service_instance, route_config) {
# Modify request for downstream service
let forwarded_path = request.path
if route_config.strip_prefix {
forwarded_path = forwarded_path.replace(route_config.strip_prefix, "", 1)
}
let service_url = f"http://{service_instance.host}:{service_instance.port}{forwarded_path}"
# Add gateway headers
let headers = {**request.headers}
headers["X-Gateway-Request-ID"] = request.id
headers["X-Forwarded-For"] = request.client_ip
headers["X-Forwarded-Proto"] = request.scheme
if request.user {
headers["X-User-ID"] = request.user.id
headers["X-User-Roles"] = request.user.roles.join(",")
}
# Forward request
let response = await http.request({
"method": request.method,
"url": service_url,
"headers": headers,
"json": request.body if request.method in ["POST", "PUT", "PATCH"] else null,
"params": request.query_params,
"timeout": 30
})
return {
"status": response.status_code,
"headers": response.headers,
"body": response.text
}
}
get_circuit_breaker(service_name) {
if service_name not in self.circuit_breakers {
self.circuit_breakers[service_name] = CircuitBreaker(
service_name: service_name,
failure_threshold: 5,
recovery_timeout: 60,
request_timeout: 30
)
}
return self.circuit_breakers[service_name]
}
}
// Saga pattern for distributed transactions
class OrderSaga {
saga_manager: SagaManager
compensation_actions: []
constructor(saga_manager) {
self.saga_manager = saga_manager
self.compensation_actions = []
}
async execute_order_processing(order_data) {
let saga_id = generate_saga_id()
try {
# Step 1: Reserve inventory
let inventory_result = await self.execute_step(
saga_id,
"reserve_inventory",
async func() {
return await self.inventory_service.reserve_items(order_data.items)
},
compensation: async func(result) {
await self.inventory_service.release_reservation(result.reservation_id)
}
)
# Step 2: Process payment
let payment_result = await self.execute_step(
saga_id,
"process_payment",
async func() {
return await self.payment_service.charge_customer(
order_data.customer_id,
order_data.total_amount
)
},
compensation: async func(result) {
await self.payment_service.refund_payment(result.payment_id)
}
)
# Step 3: Create order
let order_result = await self.execute_step(
saga_id,
"create_order",
async func() {
return await self.order_service.create_order({
**order_data,
"inventory_reservation_id": inventory_result.reservation_id,
"payment_id": payment_result.payment_id
})
},
compensation: async func(result) {
await self.order_service.cancel_order(result.order_id)
}
)
# Step 4: Send confirmation
await self.execute_step(
saga_id,
"send_confirmation",
async func() {
return await self.notification_service.send_order_confirmation(
order_result.order_id,
order_data.customer_id
)
}
# No compensation needed for notification
)
await self.saga_manager.complete_saga(saga_id)
return {
"success": true,
"order_id": order_result.order_id,
"saga_id": saga_id
}
} catch (error) {
print(f"Saga {saga_id} failed: {error.message}")
await self.compensate_saga(saga_id)
return {
"success": false,
"error": error.message,
"saga_id": saga_id
}
}
}
async execute_step(saga_id, step_name, action, compensation = null) {
try {
let result = await action()
# Record successful step
await self.saga_manager.record_step(saga_id, step_name, "COMPLETED", result)
# Store compensation action if provided
if compensation {
self.compensation_actions.append({
"saga_id": saga_id,
"step_name": step_name,
"compensation": compensation,
"result": result
})
}
return result
} catch (error) {
await self.saga_manager.record_step(saga_id, step_name, "FAILED", {"error": error.message})
throw error
}
}
async compensate_saga(saga_id) {
print(f"Starting compensation for saga {saga_id}")
# Execute compensation actions in reverse order
let compensations = self.compensation_actions.filter(c => c.saga_id == saga_id)
compensations.reverse()
for compensation in compensations {
try {
await compensation.compensation(compensation.result)
print(f"Compensated step: {compensation.step_name}")
} catch (compensation_error) {
log_error("saga_compensation_failed", {
"saga_id": saga_id,
"step_name": compensation.step_name,
"error": compensation_error.message
})
# Continue with other compensations even if one fails
}
}
await self.saga_manager.mark_saga_compensated(saga_id)
print(f"Saga {saga_id} compensation completed")
}
}
Section 4: Observability and Monitoring Architecture
Comprehensive Monitoring System
// Distributed tracing implementation
class TracingSystem {
tracer: Tracer
span_processor: SpanProcessor
exporters: []
constructor() {
self.tracer = Tracer()
self.span_processor = BatchSpanProcessor()
self.exporters = [
JaegerExporter("http://jaeger:14268/api/traces"),
PrometheusExporter("http://prometheus:9090/api/v1/write")
]
}
start_span(operation_name, parent_span = null) {
let span_context = self.create_span_context(parent_span)
let span = Span(
trace_id: span_context.trace_id,
span_id: generate_span_id(),
parent_span_id: span_context.parent_span_id,
operation_name: operation_name,
start_time: time.precise_now(),
tags: {},
logs: []
)
return span
}
create_span_context(parent_span) {
if parent_span {
return SpanContext(
trace_id: parent_span.trace_id,
parent_span_id: parent_span.span_id
)
} else {
return SpanContext(
trace_id: generate_trace_id(),
parent_span_id: null
)
}
}
finish_span(span) {
span.end_time = time.precise_now()
span.duration = span.end_time - span.start_time
self.span_processor.process_span(span)
}
// Context manager for automatic span lifecycle
trace(operation_name, parent_span = null) {
return TracingContext(self, operation_name, parent_span)
}
}
class TracingContext {
constructor(tracing_system, operation_name, parent_span) {
self.tracing_system = tracing_system
self.operation_name = operation_name
self.parent_span = parent_span
self.span = null
}
async __enter__() {
self.span = self.tracing_system.start_span(self.operation_name, self.parent_span)
return self.span
}
async __exit__(exc_type, exc_val, exc_tb) {
if exc_type {
self.span.set_tag("error", true)
self.span.log("error", {
"message": str(exc_val),
"type": exc_type.__name__
})
}
self.tracing_system.finish_span(self.span)
}
}
// Metrics collection system
class MetricsCollector {
metrics: {}
labels: {}
constructor() {
self.metrics = {}
self.labels = {}
}
counter(name, description = "", labels = {}) {
if name not in self.metrics {
self.metrics[name] = Counter(name, description)
}
return self.metrics[name].with_labels(labels)
}
gauge(name, description = "", labels = {}) {
if name not in self.metrics {
self.metrics[name] = Gauge(name, description)
}
return self.metrics[name].with_labels(labels)
}
histogram(name, description = "", buckets = null, labels = {}) {
if name not in self.metrics {
self.metrics[name] = Histogram(name, description, buckets)
}
return self.metrics[name].with_labels(labels)
}
# Business metrics helpers
track_request(method, path, status_code, duration) {
# Request counter
self.counter("http_requests_total", "Total HTTP requests").labels({
"method": method,
"path": path,
"status": str(status_code)
}).inc()
# Request duration
self.histogram("http_request_duration_seconds", "HTTP request duration").labels({
"method": method,
"path": path
}).observe(duration)
# Error rate
if status_code >= 400 {
self.counter("http_errors_total", "Total HTTP errors").labels({
"method": method,
"path": path,
"status": str(status_code)
}).inc()
}
}
track_database_operation(operation, table, duration, success) {
self.counter("database_operations_total", "Total database operations").labels({
"operation": operation,
"table": table,
"success": str(success)
}).inc()
self.histogram("database_operation_duration_seconds", "Database operation duration").labels({
"operation": operation,
"table": table
}).observe(duration)
}
track_business_event(event_type, user_id = null, additional_labels = {}) {
let labels = {"event_type": event_type, **additional_labels}
if user_id {
labels["user_id"] = user_id
}
self.counter("business_events_total", "Total business events").labels(labels).inc()
}
}
// Structured logging system
class StructuredLogger {
log_level: string
formatters: []
outputs: []
constructor(log_level = "INFO") {
self.log_level = log_level
self.formatters = [JSONFormatter()]
self.outputs = [ConsoleOutput(), FileOutput("app.log")]
}
log(level, message, context = {}) {
if not self.should_log(level) {
return
}
let log_entry = LogEntry(
timestamp: datetime.now(),
level: level,
message: message,
context: context,
trace_id: self.get_current_trace_id(),
span_id: self.get_current_span_id()
)
for formatter in self.formatters {
let formatted_log = formatter.format(log_entry)
for output in self.outputs {
output.write(formatted_log)
}
}
}
info(message, context = {}) {
self.log("INFO", message, context)
}
warning(message, context = {}) {
self.log("WARNING", message, context)
}
error(message, context = {}) {
self.log("ERROR", message, context)
}
debug(message, context = {}) {
self.log("DEBUG", message, context)
}
# Business event logging
log_user_action(user_id, action, details = {}) {
self.info(f"User action: {action}", {
"event_type": "user_action",
"user_id": user_id,
"action": action,
"details": details
})
}
log_system_event(event_type, component, details = {}) {
self.info(f"System event: {event_type}", {
"event_type": "system_event",
"component": component,
"details": details
})
}
log_business_transaction(transaction_id, transaction_type, amount = null, details = {}) {
self.info(f"Business transaction: {transaction_type}", {
"event_type": "business_transaction",
"transaction_id": transaction_id,
"transaction_type": transaction_type,
"amount": amount,
"details": details
})
}
}
Andre's Architecture Wisdom
"Architecture isn't about following patterns blindlyβit's about solving real problems with the right level of complexity. Start simple, measure what matters, and evolve your architecture as your understanding of the problem grows. The best architectures are those that your team can understand, maintain, and extend over time."
Architectural Decision Framework
- Start Simple: Begin with the simplest architecture that could work
- Measure First: Instrument everything from day one
- Evolve Gradually: Add complexity only when you have evidence it's needed
- Design for Change: Make it easy to refactor and evolve
- Consider Your Team: Architecture must match your team's capabilities
Capstone Project: E-Commerce Platform
Build a complete e-commerce platform using all the patterns from this chapter:
- Clean architecture with domain-driven design
- Event-driven communication between services
- API gateway with authentication and rate limiting
- Distributed transactions using sagas
- Comprehensive observability and monitoring
- Microservices with service discovery
Next Chapter Preview: Chapter 15 will begin our portfolio project section with building a comprehensive Web Application that demonstrates mastery of all concepts learned so far.
Remember: Great architecture emerges from understanding your domain deeply, measuring what matters, and evolving your design as you learn. The patterns you've learned here are toolsβuse them wisely to solve real problems.