07 · Designing a System from 0 to 1 (a Hands-On Methodology)
The previous six chapters gave you a mindset and a toolbox; this chapter twists them into a single follow-along pipeline that produces an architecture — and walks you through it end to end with a real example.
Opening: don't start by drawing boxes
A newcomer handed "help me design an X" most often reacts by grabbing a pen, drawing a box in the middle of the whiteboard labeled "server," then a database, and then… getting stuck.
The seasoned do it differently. For the first few minutes after getting a requirement, they draw not a single box — they just ask questions: Who uses it? For what? How many users? How fast must it be? Can data be lost? Where does the money come from? — because they know one thing:
Architecture isn't "drawn," it's "forced out" of constraints. If you haven't gotten the constraints clear, anything you draw is drawing blind.
This chapter gives you an 8-step process. It's no mystical formula — just the things from the first six chapters arranged in a sequence: first needs and constraints (02), then estimate the scale, then define boundaries, then design the data (05), then draw diagrams (03), then dive into components (04), then find bottlenecks (06), and finally look back at the trade-offs.
This process applies equally to two scenarios: designing a new system for real, and a system-design interview. The underlying moves are in fact identical — the difference is just that the interview is compressed into 45 minutes, and the interviewer cares about your process of thinking rather than the final diagram.
I. The 8-step process at a glance
See the panorama first, then take it apart. Note: these eight steps aren't a straight line you walk once and finish — they're a loop you'll circle back on again and again.
┌─────────────────────────────────────────────┐
│ │
▼ │
① Clarify needs & scope ──▶ ② Estimate scale ──▶ ③ Define use cases/API boundary │
│ │
▼ │
⑤ Draw high-level architecture ◀──────── ④ Design data model │
│ │
▼ │
⑥ Dive into key components ──▶ ⑦ Find bottlenecks, scale them │
│ │
▼ │
⑧ Review trade-offs / list risks / list open questions ──┘
(find a problem → return to any step and redo)| Step | What you're doing | Which earlier chapter |
|---|---|---|
| ① Clarify needs & scope | Ask questions first, turn vague into clear, draw the MVP boundary | 02 |
| ② Estimate scale | A back-of-the-envelope tally: users, QPS, data volume, read/write ratio | new in this chapter |
| ③ Define core use cases / API boundary | What actions does the system expose? What does the entry look like? | 02 |
| ④ Design the data model | Core entities, relationships, which store each goes into | 05 |
| ⑤ Draw high-level architecture | Context first then Container, coarse before fine | 03 |
| ⑥ Dive into key components | Pick the soul parts and drill in, applying fitting patterns | 04 |
| ⑦ Find bottlenecks, scale them | Grow 100×, what dies first? how to break it? | 06 |
| ⑧ Review trade-offs and risks | What did I give up? Where haven't I thought it through? | 06 + 08 |
Below, the methods step by step, and right after, a full example walking all eight.
Step ①: Clarify needs & scope (ask questions first, don't rush to draw)
This is the most underrated step, yet the one that opens the widest gap. A vague requirement ("build something like Twitter") hides a dozen unstated assumptions, and your job is to force them out.
The questions to ask fall into three kinds:
- Functional boundary: what does this MVP actually do, and not do? ("Do we support direct messages?" "Do we support search?" — clearly drawing out what you won't do matters more than listing what you will)
- Users and scale: who uses it? how many? how fast is the growth? (this step's answers feed straight into Step ②)
- Quality and constraints: how fast must it be? can it be briefly unavailable? can data be lost? any compliance/cost red lines? (this is exactly that checklist in 06 quality attributes)
The key mental rule: your goal isn't to "satisfy all requirements," but to "confirm which requirements actually don't matter." Every chunk of scope you cut makes the architecture an order of magnitude simpler. The newcomer wants to do everything; the master cuts relentlessly.
In an interview, this step has a hidden function: the interviewer deliberately makes the prompt vague, precisely to see whether you'll ask. Whoever buries their head and starts drawing has basically already half-failed.
Step ②: Estimate scale (back-of-the-envelope estimation)
back-of-the-envelope estimation — literally "a quick tally on the back of an envelope." Not after precision, just whether the order of magnitude is right.
Why must you estimate? Because "10,000 users" and "100 million users" are two completely different systems. The former needs just one machine and one database; the latter needs sharding, caching, and multi-active at every layer. Designing without estimating the scale is like pouring a foundation without knowing whether you're building a bungalow or a skyscraper.
Estimation needs just a few common-sense "anchor numbers" kept in your head:
┌──────────────────────────────────────────────────┐
│ A few "anchors" worth memorizing │
│ │
│ • A day ≈ 86,400 seconds, about 10^5 s │
│ (use this when estimating) │
│ • 10M daily actives, if each comes 10×/day │
│ → 100M hits/day ÷ 10^5 s ≈ 1,000 QPS (avg) │
│ • Peak is usually 2–5× the average │
│ → provision for ~3,000 QPS │
│ • Read/write ratio: social/content is usually │
│ read-heavy, 10:1 to start │
│ • A text record ~ a few hundred bytes; an image │
│ ~ a few hundred KB to a few MB │
└──────────────────────────────────────────────────┘A full worked example (feel the touch first; the formal example comes later):
Suppose we build a posting app, 10M daily actives, each posting 1 and scrolling 50 per day on average.
- Write QPS: 10M posts/day ÷ 10^5 s = 100 writes/sec (avg), peak ×3 ≈ 300.
- Read QPS: 10M × 50 = 500M hits/day ÷ 10^5 = 5,000 reads/sec, peak ≈ 15,000.
- Read/write ratio: 5,000 : 100 = 50 : 1 — classic read-heavy, and this one fact immediately tells you: caching and read-scaling are the focus, writes aren't the bottleneck.
- Storage volume: a post at 1 KB, 10M/day × 365 ≈ 3.6 TB/year (plain text). With images, at 500 KB averaged per post, that's 1.8 PB/year — a 500× difference in order of magnitude, and the storage plan is completely different.
See? A few divisions just pinned down the architecture's center of gravity: this is a read-intensive system, you pile caches on the read path; text can go in the database, images must go to object storage + CDN. These conclusions are all computed, not pulled from a hat.
💡 Estimation's value isn't in numeric precision, but in forcing you to think through "what exactly crushes this system." Reads explode? Writes explode? Storage explodes? Bandwidth explodes? — the answer differs, and the next seven steps follow.
Step ③: Define core use cases / API boundary
Treat the system as a black box and first get clear: what actions can the outside world perform on it? That's the API boundary — not specific protocols, just the "list of actions."
For a posting app, say, the core actions might be just five or six: post, delete, view someone's profile, scroll the feed, follow/unfollow. List them first, then pick 1–2 "main channels" — usually the action users hit most frequently and that most embodies the system's character (for a posting app, "scroll the feed").
Why define the boundary first? Because once the boundary is clear, the internal implementation has a target. You'll no longer agonize over "should I add this module," but ask "which use case does this module serve" — a module that serves no use case is over-engineering (_TEMPLATE.md stresses repeatedly: a part with no "why" is over-engineering).
In an interview, this step also helps you converge the battlefield: proactively saying "this system can do many things, but today I'll focus on designing the 'scroll the feed' path and set the rest aside" — a sign of maturity.
Step ④: Design the data model (picking up from 05)
The core idea of 05 Data & State is: a system's real hard part isn't logic, it's data. So once the use cases are clear, design the data immediately, not the services first.
This step does two things:
- Draw the conceptual model: what are the core entities? what relationships among them? (User — Post — Follow relationship — Like… draw it with the plainest boxes and lines, no CREATE TABLE statements)
- Pick a store shape for each kind of data: recall the key line of 05 — different data has different "access shapes," so it should go into different store types.
Following the thinking of that table in Section 7 of the AI chat product template, you should be able to fill in a row like this for each kind of data:
| Data | Access shape | Suitable store type |
|---|---|---|
| Users / follow relationships | Needs transactions, queried by relationship | Relational |
| Post content | Write-heavy, fetched by ID, simple structure | Document / append log |
| The feed (each person's list) | Massive, must be fast, recomputable | In-memory cache |
| Images / video | Large, immutable, fetched by URL | Object storage + CDN |
The newcomer's common ailment: cram everything into one relational database, then do search with
LIKEand store history in a giant table. Get this data-modeling step right and the architecture mostly flows from there; get it wrong and no amount of caching downstream will save you.
Step ⑤: Draw the high-level architecture (Context first then Container, picking up from 03)
Now, and only now, is it time to "draw boxes." But follow the order of the 03 C4 model:
- Draw Context (system context) first: treat your system as a black box and draw only its relationship with the outside world (users, third-party payment, email service…). This step confirms "where the system's boundary is, and who it interacts with."
- Then draw Container: cut the black box open one layer and draw the major blocks: client, API gateway, a few core services, several stores. This layer is enough for the first-version architecture diagram — don't rush down to the code level.
Iron rule: coarse before fine. The first diagram should be a coarse "five or six boxes + arrows"; a little ugly is fine — it just needs to make the data flow clear. Drawing each box's internals is the job of Step ⑥ later. Whoever draws twenty boxes off the bat is usually using "the diligence of drawing" to cover "the laziness of not having thought it through."
Step ⑥: Dive into key components
With the first coarse diagram done, pick 1–2 "soul parts" and drill in — not every box deserves deep digging, only the one that decides the system's success or failure. (Remember the line from the AI chat product: the soul part is the inference service, and everything else exists to "protect and feed this GPU." Every system has its "GPU.")
When diving in, this is exactly where the 04 ten core patterns come into play: this component needs decoupling? maybe event-driven; reads and writes differ too much? maybe go CQRS; need to withstand bursty traffic? insert a message queue in the middle to shave the peak. Patterns aren't for showing off — they're for answering "the specific problem this component faces."
How to tell which is the soul part? Go back to Step ②: the one crushed by scale, that's it. If reads explode, the soul part is "the feed's read path"; if writes explode, it's "writes and fan-out"; if compute explodes (like an AI product), it's "the inference service."
Step ⑦: Find bottlenecks, scale them (picking up from 06)
Ask yourself that classic question: "If users grow 100× from now, where's the first thing that can't hold up?" Then the second, the third.
This step directly reuses the estimation result from Step ②. Since the tally said it's 50:1 read-heavy, the first bottleneck is most likely on the read path: database reads smoking → the cracking means are caching, read replicas, precomputing the feed. Each bottleneck corresponds to a class of mature cracking play (exactly what each template's Section 9, "Scaling and bottlenecks," discusses).
Key: don't speak vaguely of "add caching, go sharding." Speak to the specific bottleneck computed for your system. If the bottleneck is in reads, don't go optimizing writes; if it's in bandwidth, don't go shaving CPU — hammering away at the spot that doesn't hurt is the newcomer's most common waste.
Step ⑧: Review trade-offs, list risks and open questions
The last step, and the one that best shows your skill: look back at every decision you just made, and put the costs on the table.
- Trade-offs: I picked A and gave up B — what's the cost? ("I precomputed the feed to buy blazing-fast reads, at the price of having to fan out on write and brief data inconsistency")
- Risks: which assumption, if wrong, makes the whole design collapse? ("I assumed a 50:1 read/write ratio; if a celebrity user with tens of millions of followers shows up, the fan-out explodes")
- Open questions: what haven't I thought through yet, that needs to be flagged for later?
Why does this step matter? Because there's no perfect architecture, only the architecture where "I'm clear on what I'm trading for what." Being able to state your own design's weaknesses proves you really thought it through. And these "trade-offs and reasons" are exactly what the next chapter, 08 ADR, asks you to record solemnly — every "I picked A and gave up B because…" you utter today should become an architecture decision record.
In an interview, proactively exposing weaknesses is a plus, not a minus; at work, this step is the "here's how I was thinking back then" that saves your life when you come back to review three months later.
II. Full hands-on: designing a "URL shortener service" from 0
Talking about method alone is too dry — let's pick a system that's small in size but complete in every organ and walk the eight steps end to end.
Why pick a URL shortener (turning a long URL into a short link like
s.xx/aB3xY)? Because its requirements are minimal and everyone gets it, yet it forces you to touch nearly every core architecture topic: massive reads, unique IDs, caching, a lopsided read/write ratio, store selection, hotspots… It's the best specimen for "a small system explaining big principles."Important reminder: what follows is "one person's thinking process," not "the standard answer." You can absolutely make a different choice at any step — as long as you can articulate why.
① Clarify needs & scope
Handed "build a URL shortener," I first ask, and decide for myself, a set of assumptions:
- Will do: shorten a long link into a short one; redirect to the original on visiting the short link; short links can have an expiry.
- Won't do (cut from the MVP): custom short-link aliases, click analytics, user accounts. Get the core running first, these come later.
- Quality constraints:
- Redirect must be blazing fast (a user taps and must jump immediately; latency > a few hundred ms feels bad).
- The redirect service can essentially never go down (down = every short link in the world dies, catastrophe-grade).
- Once a short link is generated, its mapping can't change, can't be lost.
- Short links must be short (the shorter the better — this is the product's value itself).
Note the most important thing I did was strike out three features. Narrow the scope and the system instantly becomes clean.
② Estimate scale (back-of-the-envelope)
Assume: 10M new short links per day, read/write ratio 100:1 (a short link exists to be clicked like crazy — classic huge reads, tiny writes).
Write QPS = 10M / day ÷ 10^5 s ≈ 100/sec (peak ×3 ≈ 300)
Read QPS = 100 × writes = ~10,000/sec (peak ≈ 30,000)
Storage (5 years):
10M/day × 365 × 5 ≈ 18 billion records
each ~ 500 bytes (short code + original link + metadata)
→ 18B × 500 B ≈ 9 TBThree decisive conclusions computed:
- Read QPS is 100× the writes → this is an extreme read-intensive system; the architecture's center of gravity is 100% on the read path, and caching is the lifeline.
- Only 9 TB in 5 years → the data volume isn't outrageous, a single store + cache can hold it, no need to shard the database off the bat.
- Must support 18 billion records → the short code must be long enough to avoid collisions. With
0-9a-zA-Z, 62 characters in all,62^7 ≈ 3.5 trillion, so a 7-character short code is more than enough. This conclusion directly defines the core algorithm.
See — a core design like "how many characters the short code should be" is computed from the estimation, not guessed. This is the power of Step ②.
③ Define core use cases / API boundary
The black box exposes just two actions:
create: given a long link, return a short code. (low-frequency, ~100 QPS)redirect: given a short code, return the corresponding long link (and redirect). (ultra-high-frequency, ~10,000 QPS)
The main channel is obvious:
redirect. Its traffic is 100× that ofcreate, and the whole system's success or failure rests on whether it's fast and stable. Every design from here serves this main channel first.
④ Design the data model
The conceptual model is simplicity itself — the core is a single entity:
┌────────────────────────────────┐
│ ShortLink │
│ ────────────────── │
│ short code (primary key, 7-ch)│
│ original long link │
│ created at │
│ expires at │
└────────────────────────────────┘Pick a store shape (recall 05: look at the access shape):
| Data | Access shape | Suitable store |
|---|---|---|
| short code → long-link mapping | Exact lookup by short code, massive, almost never changed | KV store (born for "get value by key") |
| The hot portion of that mapping | Ultra-high-frequency reads, tolerates occasional re-fetch | In-memory cache |
The key judgment: this is a pure key-value lookup problem (swap a short code for a long link), so it needs nothing of a relational database's joins and complex transactions. Forcing relational on it complicates a simple problem. Choosing a KV store is a textbook demonstration of "let the data shape decide the store type."
⑤ Draw the high-level architecture (Context first, then Container)
Context (treat the system as a black box):
┌──────────┐ tap short link / submit long link ┌──────────────────┐
│ User / │ ──────────────────────────────────▶ │ URL shortener │
│ browser │ ◀────────────────────────────────── │ service (black box)│
└──────────┘ 302 redirect / return short code └──────────────────┘Container (cut open one layer — this is the first-version diagram: coarse, just enough):
User
│
│ ① create (few) ② redirect (very many)
▼
┌─────────────────────────────────────────────┐
│ Ingress layer / API gateway │
│ (rate limiting, routing, anti-abuse) │
└───────┬──────────────────────────┬──────────┘
│ create │ redirect
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ Create service │ │ Redirect service │
│ generate unique│ │ look up code→get │
│ short code │ │ long link→302 │
└───────┬───────┘ └────────┬──────────┘
│ write │ read cache first
│ ▼
│ ┌──────────────────┐
│ │ In-memory cache │ hit? return directly
│ └────────┬─────────┘─────────────────────▶
│ write │ miss, fall back to source
▼ ▼
┌─────────────────────────────────────────────┐
│ KV store (short code → long link)│
└─────────────────────────────────────────────┘Note I deliberately split "create" and "redirect" into two paths, two services — because Step ② told me their traffic differs 100× and their read/write shapes are completely different. Let each scale independently: the redirect service can add machines like crazy, while one or two machines suffice for the create service. This is, in fact, a plain embodiment of the read-write split / CQRS idea from 04.
⑥ Dive into key components
There are two soul parts; drill into each:
(a) The redirect service (the main channel, about "fast" and "stable")
The read path must be extremely fast, so apply multi-level caching: a request first hits the in-memory cache, and a hit returns immediately (covering the vast majority of hot short links); only on a miss does it fall back to the KV store, fetch the value, and backfill the cache. Because the "short code → long link" mapping almost never changes, the cache can be set long and aggressive, and the hit rate is naturally extremely high — exactly the dividend that the 100:1 read/write ratio from Step ② handed us.
(b) The create service (about "where the short code comes from, and whether it collides")
The core hard problem: how to generate a globally unique, short, and hard-to-guess 7-character code? This is a classic fork in the road, saved for a dedicated section next.
Why drill into only these two? Because the API gateway and KV store are "mature building blocks, configured by the book," whereas short-code generation and read caching are the spots unique to this system, that are fatal if done wrong. Concentrate your energy on the cutting edge.
⑦ Find bottlenecks, scale them
"If redirect volume grows another 100× (to millions of QPS), where does it die?" Check one by one:
- First bottleneck: redirect read traffic crushes the backend. → Crack it: the cache hit rate is already high, so push it further toward the user side — cache hot short links directly to the CDN / edge nodes, so most redirects never even reach the origin. This is the standard answer for read-intensive systems.
- Second bottleneck: data grows to hundreds of TB, and a single KV can't hold up. → Crack it: shard by short code. Short codes are random, hence naturally uniform, making sharding extremely simple — another chained dividend from Step ④ choosing KV right and Step ② making short codes random enough.
- Third bottleneck: the "ID issuer" of the create service becomes a single point. → Crack it: don't ask a central authority for a number every time (it becomes a bottleneck); instead, wholesale a range of numbers to each create machine in advance, issue them locally, and wholesale the next range when they run out.
See the pattern? Nearly every bottleneck's cracking "cashes in" a foreshadowing planted in some earlier step. The clearer you thought it through earlier, the more effortless it is here — which is why you can't skip steps.
⑧ Review trade-offs, list risks and open questions
Lay out this version's costs and soft spots (this step is not a formality — it's the most honest part of the whole design):
Key trade-offs:
| I picked | Gave up | Because |
|---|---|---|
| KV store | Relational's join capability | This is a key-value lookup, joins aren't needed |
| Heavy caching + CDN | Some real-time freshness (change a link, cache may still be stale) | The mapping almost never changes, so this cost is near zero |
| Splitting create/redirect into two paths | A bit of architectural simplicity (two services, not one) | Read/write ratio 100:1, worth this complexity for independent scaling each |
| Wholesaling ID ranges to issue | Strict sequentiality/predictability of short codes | Buys no-single-point, horizontal scalability; short codes shouldn't be predictable anyway (security) |
Risks and open questions (honestly flagged):
- ⚠️ Hot short links (a single link suddenly clicked at billion-scale): the cache withstands most, but the instant the cache invalidates may crush the origin (cache breakdown). — Open: should hot keys get separate protection?
- ⚠️ Short-code exhaustion/collision: 7 chars was computed to last 5 years, but if growth far exceeds expectations, we need a contingency to bump to 8 chars in advance. — Open: monitor short-code space utilization, set an alert threshold.
- ⚠️ Reclaiming deleted/expired codes: should expired short codes be reclaimed and reused? Reuse introduces the security risk of "an old link pointing to a new target." — Open: lean toward no reuse, but confirm whether storage cost can bear it.
These three "open questions" aren't a failure of the design — they're precisely a mark of its maturity. A solution that claims "no open questions at all" only means its author hasn't thought that deep. Write them down — in the next chapter you'll learn these are exactly what should go into an ADR.
III. A thread running through it all: architecture is "iterated" into being
If there's only one sentence you remember from this chapter, it's this:
No one gets the architecture right in one shot. A good architecture is "draw a coarse one first, then grow it round by round under pressure."
Look again at why that flowchart is a loop with feedback — because the real process is never ①→②→…→⑧ in a straight line to the end:
- At Step ⑦ you find reads will explode, so you return to ④ and change the data model (add a cache table).
- At Step ⑧ you find an assumption doesn't hold, so you return to ① and re-confirm scope with the stakeholders.
- Three months after launch, real traffic arrives, and you rerun the whole thing, this time replacing "estimation" with "real monitoring data."
v1 (coarse) v2 (refined) vN (battle-honed)
┌────────┐ found ┌────────┐ real ┌────────┐
│5–6 boxes│ bottleneck│add cache│ traffic │shard/CDN│ ─▶ …
│good enuf│ ────────▶ │split svc│ ─────────▶ │multi-act│
└────────┘ to explain └────────┘ │degrade │
▲ └────────┘
└──────────── always growing ──────────────┘This is exactly the line "architecture grows" among the repo's three reading principles (see the root README). Don't fit a maturity-stage diagram onto an MVP — your URL shortener's first version may well be "one service + one KV + one cache layer," and only once it truly takes off does it grow CDN, sharding, ID ranges. Over-engineering is as harmful as not-thinking-enough.
📌 Real-world cases: verify your reasoning against a template
This chapter designed a URL shortener from 0 in eight steps. Now go verify: open this repo's URL shortener template and compare against its Section 8 (key decisions) and Section 9 (bottlenecks) — see whether the trade-offs you made while reasoning match. If they don't, no matter — as long as you can articulate why each is what it is, you're thinking like an architect.
Any template can be used this way: cover the second half, reason it out yourself with the eight steps first, then compare.
Chapter summary
- Architecture isn't drawn, it's forced out of constraints. On getting a requirement, ask questions first, estimate the scale first — don't rush to draw boxes.
- A follow-along eight-step process that produces a solution: ① clarify needs & scope → ② back-of-the-envelope scale estimate → ③ define use cases/API boundary → ④ design the data model → ⑤ draw Context first then Container → ⑥ drill into the soul parts → ⑦ find bottlenecks and scale them → ⑧ review trade-offs and risks. Each step maps to a tool from the first six chapters.
- Estimation (back-of-the-envelope) is an underrated superpower: a few divisions pin down the system's center of gravity (reads explode? writes? storage?), and every later design follows.
- Coarse before fine: the first diagram should be an ugly "five or six boxes," just enough to make the data flow clear. Drill into only the soul parts; concentrate energy on the cutting edge.
- Step eight best shows your skill: only by proactively stating what your solution gave up and where you haven't thought it through do you prove you really thought it through.
- Architecture is iterated into being: the process is a loop that circles back, not a straight line. Don't expect to get it right in one shot, and don't fit a maturity-stage architecture onto an MVP.
Now, it's your turn
Hands-on exercise: open
templates/, pick any system (e-commerce, social feed, real-time chat, video streaming…), cover Sections 4–9 first, and reason it out from scratch with these eight steps yourself — especially don't skip Step ②; tally its QPS and storage volume by hand.Once you've reasoned it out, open the template and compare: did you find the "soul part" right? Do the bottlenecks you estimated match what its Section 9 says? Are the trade-offs it makes in Section 8 the same as yours? It's fine if they differ — as long as you can articulate why each is what it is, you're already thinking like an architect.
While reasoning, you'll surely make a string of "I pick A, not B" decisions. These decisions are crystal clear in your head right now, but three months later you'll have forgotten them entirely — by then even you'll ask "why did I decide it this way?"
How do you keep these precious "whys," so the architecture can grow healthily alongside the business? That's the subject of the next chapter.
Related links
- Previous chapter: 06 · Quality Attributes & Trade-offs — the basis for judging Steps ⑦⑧ "find bottlenecks, list trade-offs" is all here
- Next chapter: 08 · Architecture Decision Records (ADR) & Evolution — record solemnly the "whys" you uttered in Step ⑧
- Companion: 02 · The Architect's Thinking Framework (Steps ①③), 03 · Reading and Drawing Architecture Diagrams Well (Step ⑤), 05 · Data & State (Step ④)
- Comparison practice: Sections 3, 4, 8, 9 of every template under
templates/are exactly the products of these eight steps; the AI chat product template is a fine example of walking the full process