Service Based Architecture Designer
by @quochungto
Design a service-based architecture with 4-12 coarse-grained domain services, including service decomposition, database partitioning strategy (shared vs doma...
clawhub install bookforge-service-based-architecture-designerπ About This Skill
name: service-based-architecture-designer description: Design a service-based architecture with 4-12 coarse-grained domain services, including service decomposition, database partitioning strategy (shared vs domain-partitioned vs per-service), API layer design, and ACID vs BASE transaction decisions. Use this skill whenever the user is designing a service-based system, decomposing a monolith into coarse-grained services, deciding how many services to create, choosing a database topology for distributed services, deciding between shared database and per-service databases, evaluating whether to add an API layer, determining ACID vs eventual consistency needs, or comparing service-based architecture against microservices β even if they don't use the exact phrase "service-based architecture." version: 1.0.0 homepage: https://github.com/bookforge-ai/bookforge-skills/tree/main/books/fundamentals-of-software-architecture/skills/service-based-architecture-designer metadata: {"openclaw":{"emoji":"π","homepage":"https://github.com/bookforge-ai/bookforge-skills"}} status: draft depends-on: - architecture-characteristics-identifier source-books: - id: fundamentals-of-software-architecture title: "Fundamentals of Software Architecture" authors: ["Mark Richards", "Neal Ford"] chapters: [13] tags: [software-architecture, architecture, service-based, distributed, domain-services, database-partitioning, ACID, coarse-grained] execution: tier: 1 mode: full inputs: - type: none description: "System description, domain requirements, team context, and data consistency needs β the skill guides the entire service-based architecture design process" tools-required: [Read, Write] tools-optional: [Grep, Glob] mcps-required: [] environment: "Any agent environment. If a codebase exists, can analyze current architecture."
Service-Based Architecture Designer
When to Use
You need to design a service-based architecture or evaluate whether service-based is the right distributed style for a system. Service-based architecture is a hybrid of microservices β it uses coarse-grained domain services (typically 4-12, averaging ~7) rather than fine-grained single-purpose services. It is considered the most pragmatic distributed architecture style. Typical situations:
Before starting, verify:
architecture-style-selector first.architecture-characteristics-identifier β you need to know what quality attributes drive the design.Context & Input Gathering
Input Sufficiency Check
This skill designs a complete service-based architecture. You can proceed with partial information and fill gaps during the process, but certain inputs directly determine the quality of the architecture.
Required Context (must have β ask if missing)
Important Context (strongly recommended β ask if easy to obtain)
Observable Context (gather from environment)
Default Assumptions
Sufficiency Threshold
SUFFICIENT: system purpose + business capabilities + cross-domain workflows are known
PROCEED WITH DEFAULTS: system purpose + capabilities are known, cross-domain workflows unclear
MUST ASK: system purpose OR business capabilities are missing
Process
Step 1: Identify Domain Services
ACTION: Decompose the system into 4-12 coarse-grained domain services based on business capabilities.
WHY: Service-based architecture uses "domain services" β coarse-grained portions of an application that encapsulate an entire business domain (like OrderService, PaymentService), NOT fine-grained single-purpose services (like OrderPlacement, OrderValidation). The coarse granularity is the defining characteristic that differentiates service-based from microservices, and it is what preserves ACID transactions and simplifies orchestration. Each domain service internally orchestrates its own sub-operations through class-level calls rather than remote service calls.
Process: 1. List all business capabilities the system must support 2. Group related capabilities into cohesive domains (aim for 4-12 groups, ~7 average) 3. Each group becomes a domain service β name it after the domain, not the technical function 4. Verify each service is coarse enough: it should contain multiple related sub-operations, not just one
Granularity checks:
IF a service only does one thing -> merge it with a related service IF a service does unrelated things -> split it into separate domain services
Step 2: Design Internal Service Structure
ACTION: Define the internal architecture of each domain service.
WHY: Each domain service is itself a mini-application with its own internal structure. Two design approaches exist: layered (technical partitioning with API facade, business logic, persistence layers) and domain-partitioned (API facade with internal sub-domain components, similar to modular monolith). The choice affects how easily the service can evolve. Domain-partitioned internal design is preferred when the service is complex enough to warrant sub-domain separation, because it makes future decomposition easier if a service eventually needs to be split.
For each service, define: 1. API facade layer: Every domain service must have an API access facade that orchestrates business requests from the UI. This facade is responsible for receiving a single business request and breaking it into internal sub-operations. 2. Internal structure: Choose layered (API facade -> business logic -> persistence) for simpler services, or domain-partitioned (API facade -> sub-domain components) for complex services. 3. Internal components: List the key components within each service.
Step 3: Select Database Topology
ACTION: Choose the database partitioning strategy for the system.
WHY: Database topology is the most consequential infrastructure decision in service-based architecture. A shared database preserves SQL joins and ACID transactions across all services β this is the primary structural advantage of service-based over microservices. However, a shared database creates coupling through schema changes: modifying a table can force redeployment of all services that use it. The database topology directly determines whether you get ACID transactions (shared) or must implement distributed transactions like SAGA (per-service). Choosing per-service databases prematurely eliminates the ACID advantage that makes service-based architecture attractive in the first place.
Decision tree:
| Strategy | When to use | Trade-offs | |----------|------------|------------| | Single shared database | Default choice. Multiple services need joins across domains. ACID transactions span service boundaries. Team is small. | Simple. Preserves ACID. But: schema changes can impact all services. Mitigate with logical partitioning. | | Logically partitioned (shared DB, domain-scoped schemas) | Want shared DB benefits but need to control schema change impact. Multiple services exist. | Best of both worlds. Services own their logical partition. Federated shared libraries match partitions. Common tables still need coordination. | | Domain-partitioned databases | 2-3 domain groups have clearly separate data with no cross-domain joins needed. | Partial isolation. Some services share a DB, others are separate. Moderate complexity. | | Per-service databases | Each service's data is truly independent. No cross-service joins needed. Team is ready for eventual consistency. | Maximum isolation. But: lose ACID across services. Need SAGA pattern for distributed transactions. Avoid unless necessary. |
IF shared database -> implement logical partitioning through federated shared libraries (one entity library per logical domain + one common library) IF per-service databases -> document which workflows now require distributed transactions and plan SAGA implementation
Critical rule: Make the logical partitioning in the database as fine-grained as possible while still maintaining well-defined data domains to better control database changes within a service-based architecture.
Step 4: Determine UI Topology
ACTION: Select the user interface deployment strategy.
WHY: Service-based architecture supports three UI variants, and the choice affects the number of architecture quanta (independently deployable units with distinct characteristics). A single monolithic UI means the entire frontend shares one deployment and one set of architecture characteristics. Domain-based or service-based UIs enable independent frontend deployments, which matters when different parts of the application face different user groups with different availability, scalability, or security needs.
Options:
| UI Topology | When to use | Quanta impact | |------------|------------|---------------| | Single monolithic UI | One user group, simple frontend, single deployment pipeline | All services + UI = 1 quantum (if shared DB) | | Domain-based UIs | Different user groups (e.g., customer-facing vs internal operations) | Multiple quanta possible β each UI + its services can be a separate quantum | | Service-based UIs | Maximum frontend independence, micro-frontend approach | Multiple quanta β each UI is coupled only to its service |
Step 5: Decide on API Layer
ACTION: Determine whether to add an API layer (reverse proxy or gateway) between the UI and services.
WHY: An API layer is optional in service-based architecture but valuable in specific scenarios. Without an API layer, the UI accesses services directly using a service locator pattern, API gateway, or proxy embedded in the UI. Adding a separate API layer creates a centralized place for cross-cutting concerns (security, metrics, auditing, rate limiting, service discovery) and is particularly important when exposing services to external consumers. However, it adds another deployment unit, network hop, and potential single point of failure.
Add an API layer when:
Skip the API layer when:
Step 6: Map Transaction Boundaries
ACTION: For each cross-domain workflow, determine whether ACID or BASE transactions are needed, and ensure the database topology supports them.
WHY: This is where service-based architecture's core advantage materializes. Because services are coarse-grained and typically share a database, most business operations that span sub-operations (like "place order + apply payment + update inventory") happen WITHIN a single domain service using regular ACID database transactions. In microservices, this same operation would span 3 separate services requiring distributed transactions (SAGA pattern), compensating transactions, and eventual consistency. The moment you split services too fine or split the database too aggressively, you lose this advantage and must deal with all the distributed transaction complexity that service-based architecture was designed to avoid.
For each cross-domain workflow: 1. List the domains involved 2. If all domains are within ONE service -> ACID transaction (simple, preferred) 3. If domains span MULTIPLE services with SHARED database -> ACID transaction still possible via shared DB 4. If domains span services with SEPARATE databases -> BASE transaction required (SAGA pattern needed)
IF many workflows require cross-service ACID transactions -> reconsider service boundaries. Services that frequently transact together may belong in the same domain service. IF BASE transactions are unavoidable -> document the SAGA choreography/orchestration and compensating actions for each workflow.
Step 7: Validate and Score
ACTION: Validate the design against service-based architecture characteristic ratings and check for anti-patterns.
WHY: Every architecture style has known strengths and weaknesses. Service-based architecture has no five-star ratings but achieves four stars in many vital areas. Validating against the ratings ensures you are not expecting the architecture to excel where it structurally cannot (like extreme elasticity at 2 stars), and checking for anti-patterns catches the most common design mistakes before they become entrenched.
Service-based architecture ratings:
| Characteristic | Rating | Notes | |---------------|:------:|-------| | Deployability | 4 | Independent service deployment without full system release | | Elasticity | 2 | Coarse services replicate more functionality than needed to scale | | Evolutionary | 3 | Good domain isolation, moderate coupling through shared DB | | Fault tolerance | 4 | One service failing does not take down others | | Modularity | 4 | Domain-partitioned, changes scoped to single service | | Overall cost | 4 | Much cheaper than microservices, event-driven, or space-based | | Performance | 3 | Fewer network calls than microservices, but still distributed | | Reliability | 4 | Less network traffic, fewer distributed transactions | | Scalability | 3 | Can scale individual services, but coarse granularity limits efficiency | | Simplicity | 3 | Simpler than other distributed styles, but still distributed | | Testability | 4 | Smaller test scope per service than monolith |
Anti-pattern checks:
Inputs
Outputs
Service-Based Architecture Design
# Service-Based Architecture Design: {System Name}Design Context
System: {what it does}
Team: {size and experience}
Key drivers: {why service-based was chosen}Domain Services ({count} services)
| # | Service | Domain | Key Components | Instances |
|---|---------|--------|---------------|:---------:|
| 1 | {ServiceName} | {domain} | {component list} | {1 or N} |
| ... | ... | ... | ... | ... |
Service Detail: {ServiceName}
Domain: {what business capability this covers}
Internal design: {layered or domain-partitioned}
Components:
{Component 1}: {responsibility}
{Component 2}: {responsibility} Database Topology
Strategy: {shared / logically partitioned / domain-partitioned / per-service}
Reasoning: {why this strategy was chosen}{If logically partitioned:}
Logical partitions:
| Partition | Tables | Used by services |
|-----------|--------|-----------------|
| {domain} | {tables} | {services} |
| common | {shared tables} | all services |
User Interface Topology
Strategy: {single monolithic / domain-based / service-based}
Reasoning: {why this topology was chosen}API Layer
Decision: {include / omit}
Reasoning: {why}Transaction Boundaries
| Workflow | Domains involved | Services | Transaction type | Notes |
|----------|-----------------|----------|:----------------:|-------|
| {workflow} | {domains} | {services} | ACID / BASE | {notes} |
Architecture Quanta
Count: {number}
Reasoning: {what determines the quantum boundaries}Characteristic Fit
| Characteristic | Rating | Meets needs? |
|---------------|:------:|:------------:|
| Deployability | 4 | {Yes/No} |
| Fault tolerance | 4 | {Yes/No} |
| ... | ... | ... |
Anti-Pattern Check
[ ] Service count in 4-12 range
[ ] No inter-service direct calls
[ ] Database topology supports required ACID transactions
[ ] Federated entity libraries (not single shared library)
[ ] No premature database splitting Getting Started
1. {First step}
2. {Second step}
3. {Third step}
Key Principles
Examples
Scenario: Electronic device recycling system Trigger: "We process old electronics (phones, tablets). Customers get quotes online, mail devices in, we assess them, pay the customer, then recycle or resell. We also have internal reporting." Process: Identified 7 domain services from the business flow: Quoting, Item Status, Receiving, Assessment, Accounting, Recycling, Reporting. Split UI into two quanta: customer-facing (Quoting, Item Status) and internal operations (Receiving, Assessment, Accounting, Recycling, Reporting). Used two separate databases β one for customer-facing operations (higher security, separate network zone) and one for internal operations. Only Quoting and Item Status services need to scale (customer traffic), others run as single instances. Output: 7 domain services, 2 architecture quanta, domain-partitioned databases (2 databases split by security boundary, not by service). Customer-facing services behind a firewall separation from internal services. ACID transactions preserved within each database boundary. Assessment service changes frequently (new device rules) but is isolated, enabling high deployability.
Scenario: Insurance claims processing platform Trigger: "We need claims intake, adjudication, payment, fraud detection, and policy verification. Team of 20 developers, currently a monolith with 4-hour deployments." Process: Identified 6 domain services: Claims Intake, Adjudication, Payment, Fraud Detection, Policy Verification, Reporting. Kept shared database because claims workflows require ACID: a claim submission must atomically create the claim record, initiate fraud check, and verify policy status. Logically partitioned the database into 6 domains + common. Added API layer because external partners (repair shops, medical providers) submit claims via API. Single monolithic UI (all internal users share the same portal). Fraud Detection needs higher throughput, so it runs multiple instances with load balancing. Output: 6 domain services, shared logically-partitioned database, API layer included. Key win: deployment time drops from 4 hours to ~30 minutes per service. ACID preserved for claims workflows. Federated entity libraries prevent cascading redeployments from schema changes.
Scenario: E-learning platform Trigger: "Building a learning management system with course catalog, enrollment, content delivery, progress tracking, assessments, and certificates. Team of 10, first distributed system." Process: Identified 6 domain services: Course Catalog, Enrollment, Content Delivery, Progress Tracking, Assessment, Certification. Shared database β enrollment needs ACID with progress tracking (enrolling a student must atomically create progress records). No API layer needed (internal platform only). Single UI. Default single instances per service since traffic is predictable (students access during class hours). Kept Assessment and Certification in separate services despite being related because assessment rules change frequently (high deployability need) while certification is stable. Output: 6 domain services, single shared database with logical partitioning, no API layer. Team's first distributed system β service-based is ideal because it's the simplest distributed style (simplicity 3, cost 4) while still gaining independent deployability (4) and fault tolerance (4). If Content Delivery later needs CDN-level scaling, it can be extracted into a separate quantum.
References
architecture-style-selectorarchitecture-characteristics-identifierarchitecture-decision-record-creatorLicense
This skill is licensed under CC-BY-SA-4.0. Source: BookForge β Fundamentals of Software Architecture by Mark Richards, Neal Ford.
Related BookForge Skills
Install related skills from ClawhHub:
clawhub install bookforge-architecture-characteristics-identifierOr install the full book set from GitHub: bookforge-skills
β‘ When to Use
π‘ Examples
Scenario: Electronic device recycling system Trigger: "We process old electronics (phones, tablets). Customers get quotes online, mail devices in, we assess them, pay the customer, then recycle or resell. We also have internal reporting." Process: Identified 7 domain services from the business flow: Quoting, Item Status, Receiving, Assessment, Accounting, Recycling, Reporting. Split UI into two quanta: customer-facing (Quoting, Item Status) and internal operations (Receiving, Assessment, Accounting, Recycling, Reporting). Used two separate databases β one for customer-facing operations (higher security, separate network zone) and one for internal operations. Only Quoting and Item Status services need to scale (customer traffic), others run as single instances. Output: 7 domain services, 2 architecture quanta, domain-partitioned databases (2 databases split by security boundary, not by service). Customer-facing services behind a firewall separation from internal services. ACID transactions preserved within each database boundary. Assessment service changes frequently (new device rules) but is isolated, enabling high deployability.
Scenario: Insurance claims processing platform Trigger: "We need claims intake, adjudication, payment, fraud detection, and policy verification. Team of 20 developers, currently a monolith with 4-hour deployments." Process: Identified 6 domain services: Claims Intake, Adjudication, Payment, Fraud Detection, Policy Verification, Reporting. Kept shared database because claims workflows require ACID: a claim submission must atomically create the claim record, initiate fraud check, and verify policy status. Logically partitioned the database into 6 domains + common. Added API layer because external partners (repair shops, medical providers) submit claims via API. Single monolithic UI (all internal users share the same portal). Fraud Detection needs higher throughput, so it runs multiple instances with load balancing. Output: 6 domain services, shared logically-partitioned database, API layer included. Key win: deployment time drops from 4 hours to ~30 minutes per service. ACID preserved for claims workflows. Federated entity libraries prevent cascading redeployments from schema changes.
Scenario: E-learning platform Trigger: "Building a learning management system with course catalog, enrollment, content delivery, progress tracking, assessments, and certificates. Team of 10, first distributed system." Process: Identified 6 domain services: Course Catalog, Enrollment, Content Delivery, Progress Tracking, Assessment, Certification. Shared database β enrollment needs ACID with progress tracking (enrolling a student must atomically create progress records). No API layer needed (internal platform only). Single UI. Default single instances per service since traffic is predictable (students access during class hours). Kept Assessment and Certification in separate services despite being related because assessment rules change frequently (high deployability need) while certification is stable. Output: 6 domain services, single shared database with logical partitioning, no API layer. Team's first distributed system β service-based is ideal because it's the simplest distributed style (simplicity 3, cost 4) while still gaining independent deployability (4) and fault tolerance (4). If Content Delivery later needs CDN-level scaling, it can be extracted into a separate quantum.