From Furniture Store To Software
Borough Furniture Store starts as a business idea, not as a collection of microservices. Customers need to discover products, maintain a basket, buy available stock, pay safely and receive their orders. The application layer is where those business capabilities are translated into executable behaviour.
The purpose of this collection is therefore to explain how bfstore works as software: what rules must remain true, where responsibilities live, how services communicate, which data each service owns, how customer journeys cross service boundaries and what the application does when parts of the system fail.
The Application's Role
The application owns the behaviour of the ecommerce system. It defines the domain model, service responsibilities, synchronous and asynchronous contracts, persistence boundaries and the workflows that combine independent services into useful business outcomes.
Application Scope
Keeping this boundary explicit prevents implementation details from swallowing the business story. The application describes what the software requires from its runtime; the developer platform provides repeatable ways to build and run it; each cloud implementation supplies provider-native infrastructure and controls.
Where The Application Layer Fits
Application At A Glance
The application is being built incrementally. The first working slice establishes product discovery and basket management before the project expands into the checkout, inventory, payment, order and fulfilment flows that make the system a richer distributed application.
Architecture In Brief
bfstore separates business capabilities into services only where an independent boundary is useful. Each service owns a defined responsibility and, where it persists state, owns that persistence boundary rather than sharing tables as an integration mechanism.
Communication In Brief
Synchronous interactions use gRPC contracts when the caller needs an immediate answer. Business facts that other parts of the system can react to independently are represented as events. This gives bfstore a hybrid communication model rather than forcing every interaction through either request-response or messaging.
Data Ownership In Brief
A service may read and mutate its own state directly. Other services collaborate through published contracts or events. This keeps ownership visible and prevents apparently convenient cross-service database access from becoming a hidden coupling mechanism.
Current Implementation Status
| Area | Status | Current position |
|---|---|---|
| Catalog service | Implemented v1 local slice | Product and variant discovery, MySQL persistence, gRPC, health, telemetry and tests. |
| Basket service | Implemented v1 local slice | Basket lifecycle and item operations with Catalog validation, persistence, health, telemetry and tests. |
| Browse → Basket workflow | Implemented + smoke-tested | Catalog and Basket collaborate through the first cross-service customer journey. |
| Inventory | Planned | Stock ownership and reservation boundary for the checkout slice. |
| Checkout | Planned | Cross-service workflow spanning basket, inventory, payment, order and fulfilment behaviour. |
| Payment, Order, Shipping, Notification | Planned | Commerce and fulfilment capabilities introduced as the checkout vertical slice grows. |
| Search, Review, Recommendation | Planned | Later customer-facing capabilities built after the core commerce path is established. |
Explore The Application
The deeper application documentation is organised around four questions. What does the business require? How is the software designed? What does each service own? And how do those services collaborate to fulfil complete customer journeys?
Explore business capabilities, domain concepts, invariants, requirements and customer journeys before technical boundaries are introduced.
Application ArchitectureSee How Those Requirements Shape The SoftwareFollow service boundaries, communication, events, data, consistency, resilience, security, observability, scaling and testing.
ServicesExamine Each Ownership BoundaryOpen the service dossiers for responsibilities, contracts, data, events, dependencies, failure modes, signals, scaling and evidence.
WorkflowsFollow Behaviour Across Service BoundariesTrace customer and business journeys through commands, events, state changes, failure paths and recovery behaviour.
The Application Landscape
Service names are not the starting point for the design. bfstore first identifies the capabilities the business needs, then assigns responsibility to service boundaries where independent ownership is useful. Those boundaries can change as implementation provides better evidence.
Business Capabilities
- Product discoveryPresent products, categories, variants and attributes that customers can browse and select.
- Basket managementMaintain the customer's intended purchase before checkout begins.
- Inventory managementOwn stock truth and control whether stock can be reserved for an order.
- CommerceCoordinate checkout, payment, order creation and the transition into fulfilment.
- FulfilmentTurn a confirmed order into shipment and customer-facing delivery progress.
- Discovery & engagementSupport search, reviews and recommendations without making those projections the source of product truth.
Service Landscape
The target landscape currently includes Catalog, Basket, Inventory, Order, Payment, Shipping, Notification, Search, Review and Recommendation. Catalog and Basket form the first implemented slice; the remaining boundaries are design targets that will be validated as their workflows are built.
Service Relationships
A service is useful because of the capability it owns, not because it exists in isolation. The landscape therefore shows both current implementation and the direction of travel, while deliberately keeping runtime and cloud infrastructure out of the application view.
bfstore Application Landscape
How bfstore Communicates
bfstore uses different communication styles for different business needs. An immediate command or query should not be turned into an event simply because a broker exists; equally, a completed business fact should not require every interested service to be called synchronously.
Synchronous Interactions
gRPC is used where one service needs an immediate response from another. The current Basket slice demonstrates this directly: when an item is added, Basket validates the selected product and variant through Catalog before accepting the item into basket state.
Business Events
As checkout and fulfilment are implemented, business facts such as stock being reserved, payment being authorised or an order being created can be published so that interested services react independently. Event semantics, delivery behaviour, idempotency, ordering and recovery belong in the dedicated event architecture rather than being hidden inside service implementation notes.
Contracts
Protocol Buffers define application contracts. Contract evolution is treated as an application design concern: messages and RPCs must remain reviewable, versionable and testable as services evolve independently.
Application Data
Data ownership follows service ownership. A service can change its own state directly, but another service does not gain ownership simply because the same information would be convenient to query from its database.
Service-Owned Data
Catalog owns product catalog truth. Basket owns basket state. As later slices are implemented, Inventory will own stock, Payment will own payment state and Order will own orders. Each boundary can choose persistence structures that support its responsibilities while exposing information to other services through contracts or events.
Derived Data And Projections
Some capabilities need data shaped for a different access pattern. Search is the clearest example: its index can contain a denormalised product projection for fast discovery without becoming the governed source of product truth. That distinction lets bfstore optimise reads without blurring ownership.
Building For Failure And Change
A distributed application is defined as much by what happens when dependencies are slow, unavailable or inconsistent as by its successful request path. bfstore therefore treats failure behaviour, security, telemetry and validation as part of the application design rather than post-build decoration.
Failure Is Part Of The Design
Services need explicit deadlines, bounded retries, idempotent operations where requests may be repeated, graceful shutdown and safe behaviour when dependencies fail. As asynchronous workflows arrive, poison messages, duplicate delivery and compensation become first-class design concerns too.
Observability
Application signals need to make a customer journey understandable across service boundaries. The current Catalog and Basket slices already establish the pattern with structured logging, correlation identifiers, OpenTelemetry tracing, request metrics and database metrics. Later workflows extend that correlation across additional services and events.
Security And Trust
The application defines what must be authenticated and authorised, which operations belong to a customer or privileged actor, what secrets a service requires and where service-to-service trust exists. Cloud-specific mechanisms used to satisfy those requirements are documented separately in each provider implementation.
Testing And Validation
Tests are part of the evidence chain. Unit and repository tests validate local behaviour, contract and integration tests validate boundaries, and smoke tests prove complete slices. Failure, load and recovery experiments can then test assumptions that are difficult to establish through unit tests alone.
The Implementation Journey
bfstore is intentionally built in vertical slices. A service is not treated as finished merely because its package structure exists; each slice should prove useful behaviour together with its contracts, persistence, health, telemetry, tests and interactions with the rest of the application.
The First Vertical Slice: Browse To Basket
The first working cross-service journey combines Catalog and Basket. A customer can discover an active product and variant through Catalog, create a basket and add that selection to it. Basket validates the product/variant through Catalog before persisting basket state, and the repository includes a repeatable local smoke flow that exercises both services together.
First Vertical Slice: Browse To Basket
The Next Vertical Slice: Checkout
Checkout is the next major application expansion. It introduces the boundaries needed to reason about stock reservation, payment authorisation, order creation, fulfilment and the failure cases created when one customer action spans several independently owned services.
The checkout documentation will only mark those behaviours as implemented when the corresponding contracts, code and validation exist. Until then they remain explicit design targets rather than implied capabilities.
Evolution Of The Architecture
The service landscape is a design hypothesis that implementation is allowed to challenge. If a boundary creates needless coupling, a workflow exposes missing ownership or a service does not justify independent operation, the architecture should change and the relevant ADR should record why.
Repository And Engineering Evidence
The application source of truth is the mantrobuslawal/bfstore repository. The website explains the intended architecture; the repository shows how much of that architecture has been implemented and validated at a particular point in time.
Where Things Live
| Concern | Repository area | What it demonstrates |
|---|---|---|
| Service implementation | services/ |
Service boundaries, business logic, adapters, runtime composition and service-specific tests. |
| Contracts | proto/ |
Versioned Protocol Buffer contracts shared across service boundaries. |
| Persistence | db/ |
Service-owned migrations, seeds and database lifecycle assets. |
| Architecture & requirements | docs/ |
Design intent, requirements, APIs, events, data, security, observability, testing and operational notes. |
| Decisions | adr/ |
Context and trade-offs behind significant application decisions. |
| Validation | tests/ and scripts/ |
Cross-service checks, smoke flows and repeatable validation beyond package-level tests. |
From Design To Evidence
Wherever practical, application documentation should let a reader move from a business expectation to the artefacts that prove the current implementation.
This traceability is intentionally two-way. A design page should link to code and tests where they exist; repository evidence should link back to the requirement or decision it implements when doing so improves understanding.
Continue Exploring
The Application index is intentionally the map rather than the encyclopedia. The next level of the collection separates business meaning, application-wide design, individual ownership boundaries and cross-service behaviour so that each topic can go deep without losing its place in the wider system.
Business capabilities, domain model, invariants, requirements and customer journeys.
02 · ArchitectureHow Should The Application Make It True?Boundaries, contracts, events, persistence, consistency, resilience, security, observability, scaling and testing.
03 · ServicesWho Owns Each Part Of The Behaviour?One dossier per service covering responsibilities, contracts, data, dependencies, signals, failure and evidence.
04 · WorkflowsHow Do The Pieces Become A Working Business System?End-to-end journeys across synchronous calls, events, state changes, failure paths and recovery.