Skip to content

Commit 4d93f89

Browse files
committed
Update architect for flow pattern
1 parent ec9f81c commit 4d93f89

File tree

1 file changed

+153
-38
lines changed

1 file changed

+153
-38
lines changed

patterns/architect-for-flow.md

Lines changed: 153 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,178 @@
33
- [Architect for flow](#architect-for-flow)
44
- [Context](#context)
55
- [The pattern](#the-pattern)
6+
- [The mindset](#the-mindset)
7+
- [Core concepts and how they fit together](#core-concepts-and-how-they-fit-together)
8+
- [Independent value streams (Lean Thinking)](#independent-value-streams-lean-thinking)
9+
- [Stream-aligned teams (Team Topologies)](#stream-aligned-teams-team-topologies)
10+
- [Services, products, and ownership](#services-products-and-ownership)
11+
- [Bounded contexts and domain alignment](#bounded-contexts-and-domain-alignment)
12+
- [Fast flow through small batches](#fast-flow-through-small-batches)
13+
- [Co-creation, codesign, and coevolution](#co-creation-codesign-and-coevolution)
614
- [Benefits](#benefits)
7-
- [Caveats](#caveats)
8-
- [Details](#details)
15+
- [Practical guidance](#practical-guidance)
916
- [Examples](#examples)
1017

1118
## Context
1219

13-
- These notes are part of a broader set of [principles](../principles.md)
14-
- This pattern is closely related to the [deliver little and often](little-and-often.md) pattern
15-
- See also: [structured code](../practices/structured-code.md)
20+
- This pattern is part of a broader set of [engineering principles](../principles.md).
21+
- It strongly complements the [deliver little and often](./little-and-often.md) pattern.
22+
- It aligns with modern thinking on architecture modernisation, [evolutionary design / domain-driven design (DDD)](https://martinfowler.com/tags/evolutionary%20design.html), [Team Topologies](https://teamtopologies.com/key-concepts), and [Better Value Sooner Safer Happier (BVSSH)](https://www.soonersaferhappier.com/post/what-is-bvssh).
23+
- It should be read alongside [structured code](../practices/structured-code.md).
24+
25+
At its core, _architecting for flow_ is about designing systems and teams so that valuable change can move quickly, safely, and sustainably from idea to production.
1626

1727
## The pattern
1828

19-
Technical design choices should primarily optimise for rapid, reliable delivery and operations.
29+
Design architecture to enable fast, safe flow of change across independent value streams.
2030

21-
One key consideration is how best to break the system down into independent services/components.
31+
Architecting for flow means intentionally shaping systems around:
2232

23-
## Benefits
33+
- Independent value streams
34+
- Stream-aligned teams
35+
- Clear bounded contexts
36+
- Loosely coupled services and products
37+
38+
The primary goal is not technology elegance, reuse, or theoretical purity. The goal is fast flow, which is the ability for teams to deliver small, incremental changes frequently, with confidence.
39+
40+
This requires aligning business domains, team ownership, services/products, and architecture boundaries so that:
41+
42+
- teams can work independently
43+
- changes are small and low-risk
44+
- coordination and hand-offs are minimised
45+
- learning happens early and often
46+
47+
## The mindset
48+
49+
Modern architecture recognises that software systems do not exist in isolation. Their behaviour, quality, speed of change, and reliability are shaped just as much by people, team structures, incentives, and ways of working as by code, infrastructure, or technologies.
50+
51+
Poorly shaped architectures create:
52+
53+
- Change coupling across teams
54+
- Slow delivery and high coordination costs
55+
- Fragile systems and risky releases
56+
- Unhappy, frustrated engineers and users
57+
58+
Well-shaped architectures enable:
59+
60+
- Independent delivery
61+
- Faster learning
62+
- Better quality
63+
- Safer change
64+
- Happier teams and users
65+
66+
Architecting for flow is therefore a business optimisation strategy, not just an engineering one.
67+
68+
## Core concepts and how they fit together
69+
70+
### Independent value streams (Lean Thinking)
71+
72+
An **independent value stream** is the fundamental building block. Each value stream:
73+
74+
- Is aligned to a business subdomain
75+
- Is owned by a single stream-aligned team
76+
- Delivers business outcomes, not just features
77+
- Can be developed and deployed independently
78+
79+
Architecture should make independence real, not just aspirational.
80+
81+
### Stream-aligned teams (Team Topologies)
82+
83+
Each independent value stream is owned by a **stream-aligned team**. That team:
84+
85+
- Owns the product or service end-to-end
86+
- Makes day-to-day product and technical decisions
87+
- Builds, deploys, operates, and improves what they own
88+
- Optimises for outcomes and flow, not hand-offs
89+
90+
Architecture should reduce the need for teams to coordinate in order to deliver change.
2491

25-
In high level terms, systems which are designed to maximise rapid, reliable delivery and operations:
92+
### Services, products, and ownership
2693

27-
- Are cost efficient: teams don't waste their time fighting the tools or working with difficult architectures
28-
- Improve business agility: these systems allow teams to respond more quickly to changes
29-
- Improve reliability: these systems are easier to understand, which leads to fewer failures and shorter recovery times
30-
- Improve team happiness: engineers are happy when the tools they work with let them get on with what they do best
94+
Architecting for flow means aligning:
3195

32-
In many cases, building a system as a set of independently running services/components has benefits:
96+
- Products and services
97+
- Codebases and repositories
98+
- Runtime boundaries
99+
- Team ownership
33100

34-
- Multiple components enable parallel development work by multiple teams
35-
- Teams can work at their own cadence
36-
- Changes with each component are easier to reason about and test
37-
- The best tools can be chosen for each job, rather than being hampered by a common set of technologies which need to be adequate for all parts of the system but may only suit some parts of the system well
38-
- Concerns such as scaling, resilience, etc, can be tailored on a per-component basis — for example avoiding the waste generated by scaling a monolith for the benefit of scaling one small aspect of the system
39-
- It is possible to isolate the impact of catastrophic failure of any individual component
40-
- Self-contained components with clear boundaries of responsibility reduce hand-offs between teams
41-
- Components with clear boundaries of responsibility are more easily replaced
42-
- Components with clear boundaries of responsibility more likely to be reusable — note: this does not promote building "generic" components — rather, components that have a clear scope
101+
A common smell is when:
102+
103+
- Multiple teams must change their services together
104+
- Features require cross-team coordination by default
105+
- Teams share databases or internal implementation details
106+
107+
Instead:
108+
109+
- Each service or product should map clearly to a value stream
110+
- Ownership boundaries should be obvious
111+
- Dependencies should be explicit and intentional
112+
113+
### Bounded contexts and domain alignment
114+
115+
Clean **bounded contexts** are essential to flow. Key principles:
116+
117+
- Split systems vertically by domain, not horizontally by technical layers
118+
- Avoid shared databases across bounded contexts
119+
- Encapsulate data, logic, and behaviour within each context
120+
- Accept duplication where it reduces coupling and coordination
121+
122+
Bounded contexts reduce change coupling, allowing teams to move independently. Collaborative techniques such as [EventStorming](https://www.eventstorming.com/) are strongly encouraged to identify meaningful domain boundaries.
123+
124+
### Fast flow through small batches
125+
126+
Flow improves when teams:
127+
128+
- Deliver small slices of value
129+
- Deploy frequently
130+
- Learn quickly from real usage
131+
- Reduce the blast radius of change
132+
133+
Architecture should actively support:
134+
135+
- Independent deployments
136+
- Progressive delivery
137+
- Feature toggling
138+
- Observability and fast feedback
139+
140+
Large, coordinated releases are a sign that flow is being constrained by architecture.
141+
142+
## Co-creation, codesign, and coevolution
143+
144+
Architecting for flow is not a one-off design activity. It requires a **co-creation approach**, where:
145+
146+
- Engineers, product managers, domain experts, and users collaborate
147+
- Architecture evolves incrementally
148+
- Decisions are revisited as learning increases
149+
150+
Architecture should be **codesigned and coevolved** with the system:
151+
152+
- Changes are made in small, safe steps
153+
- Learning feeds back into design
154+
- Teams continuously improve both the product and the architecture
155+
156+
This is a deliberate move away from big up-front designs.
157+
158+
## Benefits
43159

44-
## Caveats
160+
Systems architected for flow tend to deliver strong outcomes. However
45161

46-
- This pattern must not compromise quality: automation (including of quality control) is essential for safe implementation of this pattern
47-
- Architectures with multiple moving parts are more complicated. While splitting a system into multiple components is often a good idea, "too many" components can cause more harm than good. There is usually a sweet spot for how many components to break a system down into — and for small or simple systems a monolith might be better. In distributed systems:
48-
- There are more failure modes to test, since calls which go over the network can fail in more ways than simple method invocations
49-
- Versioning becomes a more complicated concern, and additional effort is required to ensure component APIs are compatible as each changes independently
50-
- Clean domain boundaries are essential for safe implementation of this pattern
51-
- Comprehensive monitoring and alerting is essential for safe implementation of this pattern
52-
- Components should be built because working in that way gives benefits, not purely because the components might be reused later: if they are later reused, that's even better
162+
- Flow must not compromise quality, strong automation is essential (testing, security, deployment)
163+
- More components ≠ better as over-fragmentation increases cognitive load and operational cost, small or simple systems may benefit from a well-structured modular monolith
164+
- Distributed systems introduce complexity, network failures has to be factored in, versioning challenges become a norm, observability becomes mandatory
165+
- Reuse is not the primary goal, build components for clear ownership and flow, reuse is a secondary benefit, not a justification
53166

54-
## Details
167+
There is usually a sweet spot between monoliths and over-distributed systems.
55168

56-
- Split services vertically via [bounded contexts](https://martinfowler.com/bliki/BoundedContext.html) rather than horizontally via technology layers: for example, do not implement dedicated processes to update databases or configuration
57-
- For components to be genuinely independent they need to only interact via their public APIs (e.g. not via a shared database)
58-
- Components should handle the entirety of their bounded context, for example persistence, logic and presentation (though obviously not all components will involve all of these layers)
59-
- This pattern applies to existing services as well as greenfield development projects — please see Martin Fowler's [StranglerFigApplication blog](https://martinfowler.com/bliki/StranglerFigApplication.html)
169+
## Practical guidance
60170

61-
TO DO: reference to the NHS UI toolkit (for presentation fragments)
171+
- Split systems by bounded context, not by technical layers
172+
- Avoid shared databases between components
173+
- Ensure components interact only via public APIs (external to the internal service API)
174+
- Design services so a single team can change and deploy them independently
175+
- Align repositories, pipelines, and runtime ownership with team boundaries
176+
- Apply this pattern to existing systems as well as greenfield work, techniques like the [Strangler Fig](https://martinfowler.com/bliki/StranglerFigApplication.html) pattern can help evolve legacy systems safely
62177

63178
## Examples
64179

65-
TO DO
180+
We have examples of live systems where this pattern has been applied in practice and continues to evolve. If you would like to explore concrete examples, including what worked well, what was learned, and where trade-offs were made, please get in touch. These systems can be discussed collaboratively and used as shared learning opportunities to help teams apply the pattern effectively in their own contexts.

0 commit comments

Comments
 (0)