Full course · No. 03
A course for the engineer who already writes code but wants to learn how to make architectural decisions, explain them to the team and the business, and see the system whole.
24 modules · trade-offs instead of dogma · professional vocabulary in plain language
- 01. Who the architect is
- 02. Trade-offs
- 03. Technical debt
- 04. Cognitive load
- 05. Decomposition
- 06. Layers and dependencies
- 07. APIs and contracts
- 08. Data model
- 09. State
- 10. Distributed systems
- 11. Monolith and microservices
- 12. Sync and async
- 13. Performance
- 14. Scalability
- 15. Reliability
- 16. Security
- 17. Observability
- 18. Documentation
- 19. Communication
- 20. Leadership without authority
- 21. Business and product
- 22. AI-native architect
- 23. Anti-patterns
- 24. Continuous growth
An architect differs from a senior engineer not because they know more technologies. They own the consequences of decisions over time.
The architect thinks in years
An engineer builds a bridge that a car will drive across tomorrow. The architect asks what happens when trucks start using it, when a new district goes up next door, and when repairs cost more than the bridge itself.
An engineer usually solves the problem as posed. The architect first checks whether the problem was posed correctly. That isn't snobbery or a wish to "talk about the deep stuff." An architectural decision is just usually more expensive to change than a line of code.
The main shift in the head: you stop asking only "how do I do X" and start asking "why do we need X, what are the alternatives, what will we lose, and what will this look like in three years".
The architect's responsibility is the shape of the system, not the code
If a carpenter hangs a shelf wrong, you can move it. If the designer puts a load-bearing wall in the wrong place, the house lives with that mistake for decades.
The architect isn't obliged to personally make every technical decision. But they are obliged to own the decisions that set the shape of the system: service boundaries, the data model, integration protocols, the scaling strategy, security, observability, the migration path.
The useful distinction here is between reversible decisions and irreversible decisions. A reversible decision can be changed in a day or a week: a logging library, a button colour, the internal structure of a small module. An irreversible or expensive-to-reverse decision changes the trajectory of the system: the database, the tenancy model, an API contract, the way events are stored, service boundaries.
- What problem are we actually solving? - What changes if load grows 10x? - Which decisions here are reversible, and which are nearly not? - Who's going to be maintaining this a year from now?
The architect doesn't build "the most correct system" — they build a system that survives reality.
There are no free decisions in architecture. Every choice buys one property at the cost of another.
Best practice without context is bad advice
An SUV beats a sedan on a muddy road. The sedan beats the SUV in the city. A bicycle beats both if you need to go three blocks and there's nowhere to park.
You can't evaluate an architectural decision outside its context. REST, GraphQL, Kafka, PostgreSQL, Kubernetes, microservices, monolith — all of these are tools with a price. A trade-off is a deliberate exchange: latency vs. throughput, consistency vs. availability, time-to-market vs. maintainability, simplicity vs. flexibility.
The architect doesn't say "Kafka is better than RabbitMQ." They say: "we need per-key event ordering, high throughput, replay, and a durable log; in exchange we pay the operational complexity of Kafka." That's what professional language sounds like.
Complexity is a tax
Every new abstraction is like another room in the house. The room can be useful, but it has to be cleaned, heated, repaired, and explained to guests.
Complexity is useful when it buys an important property: failure isolation, independent release, security, scaling, testability. But complexity "for the future" usually becomes a permanent tax.
The terms over-engineering and under-engineering are only useful together. Over-engineering: complexity showed up before the real pain. Under-engineering: the system has already hit limits, and the architecture left no room to grow. The architect's job isn't to pick an extreme — it's to hold the middle.
- Architecture: The Hard Parts — Ford, Richards, Sadalage, Dehghani
- Software Architecture in Practice — Bass, Clements, Kazman
- Martin Fowler: Is Design Dead?
Technical debt isn't always bad. What's bad is debt taken on by accident, not written down, and never meant to be repaid.
Debt is a loan, not garbage
A loan on equipment can accelerate a business. A loan for a party just leaves a hangover and interest.
Technical debt is a decision that speeds us up now but creates a future cost of change. Sometimes that's right: you need to test the market, hit a deadline, keep a customer. The problem starts when the team labels everything as debt: bad code, missing tests, chaotic dependencies, outdated libraries.
A useful model is Martin Fowler's quadrant: deliberate / inadvertent and prudent / reckless. Deliberate-prudent debt: "we're skipping multi-region for now because we have 200 users and one market." Inadvertent-reckless debt: "we didn't know we needed transactions."
Debt charges interest
If the road is broken, every trip takes five minutes longer. A month later it's no longer a pothole — it's a tax on the whole city.
The interest on technical debt is the slowdown of every next change. The more often the team touches an area, the more expensive the debt. That's why debt in the hot domain is more dangerous than debt in a rarely-used admin panel.
The architect negotiates a repayment strategy: what exactly counts as debt, what risk it creates, when we revisit the decision, what signal says "time to pay." Without that, "technical debt" becomes an emotional argument, not a managed instrument.
- Where is it written down why we took this compromise?
- What interest are we paying each sprint?
- What would have to happen for this debt to become a blocker?
- Is there a repayment plan, or at least a trigger for revisiting?
A system nobody can hold in their head will break even with strong engineers.
Architecture has to fit in a human head
A subway map is useful not because it shows every bolt in the tunnel. It shows lines, transfers, and direction of travel. That's enough to make a decision.
Cognitive load is the mental effort a system demands from an engineer. There's intrinsic load: the complexity of the domain itself. There's extraneous load: extra complexity from bad architecture, non-obvious links, accidental exceptions, and magic. The architect can't remove business complexity, but they're obliged to reduce accidental complexity.
A good module can be understood on its own. A good bounded context has its own language and its own invariants. A good team owns an area that fits in its head.
Conway's Law isn't a joke
If three departments don't talk to each other, their product almost always looks like three products glued together in one menu.
Conway's Law says: an organisation designs systems that mirror the structure of communication inside the organisation. If architectural boundaries don't match team boundaries, the team will keep crossing someone else's turf.
Team Topologies introduces useful labels: stream-aligned team, platform team, enabling team, complicated-subsystem team. That isn't HR fashion — it's an architectural tool. Sometimes the right decomposition of the system starts with the right decomposition of responsibility.
A big system becomes manageable only when you can cut it along the right boundaries.
You can cut by layers, by domains, or by data flow
A butcher doesn't cut a carcass at random — they cut at the joints. Good decomposition also looks for natural break points.
Decomposition isn't "sort into folders." It's choosing where responsibility ends. High cohesion means everything inside a component is about one thing. Low coupling means the component knows little about other components.
A horizontal cut gives you layers: UI, application, domain, infrastructure. A vertical cut gives you features or bounded contexts: billing, identity, catalog, comments. Real systems need both, but mixing one for the other is dangerous.
A bad boundary gives itself away through change
If replacing the kitchen tap means tearing the bedroom apart, the problem isn't the tap.
A sign of bad decomposition: a small change ripples across five modules. Another sign: one module changes for different reasons — today because of product, tomorrow because of the database, the day after because of an integration.
The DDD term bounded context is useful precisely here. It's a boundary inside which words have a single meaning. "Customer" in billing and "Customer" in support can be different models. Forcing them into one often creates a brittle "universal" model.
Business logic should depend on business rules, not on the framework, the database, or HTTP.
Dependencies should flow toward the centre
The foundation shouldn't depend on the colour of the curtains. If it does, the house was designed backwards.
Clean Architecture, Hexagonal Architecture, and Onion Architecture all say the same thing: the important logic belongs at the centre, the details on the outside. HTTP, SQLAlchemy, Next.js, Kafka, Redis, Stripe — these are details. They matter, but they shouldn't define business rules.
The Dependency Inversion Principle says: high-level logic depends on abstractions, and implementations get plugged in from outside. In code that looks like ports and adapters: the service receives a PaymentGatewayProtocol, it doesn't construct a StripeClient inside itself.
Abstraction exists to absorb change, not to look nice
An adapter belongs where the plugs are actually different. If you put an adapter in every socket just because you like adapters, the house gets less safe.
Not every class needs an interface. But anything touching the outside world, time, randomness, the network, the file system, or the database should be replaceable in tests. Otherwise you're not testing business logic — you're booting a small production system inside a unit test.
The price of a layer is more files and more words. The payoff is testability, infrastructure that can be swapped, clean boundaries. If there's no payoff, the layer is dead weight.
An API is a promise. Breaking a promise is easy; rebuilding client trust is hard.
The contract matters more than the transport
Passport control doesn't care about the brand of the door. What matters is which documents are accepted, which rules apply, and what happens when something is wrong.
REST, GraphQL, gRPC, and WebSocket are different ways to talk. REST suits resource-oriented APIs and simple caching. GraphQL helps when different clients need different shapes of read. gRPC is good for typed service-to-service communication. WebSocket is for real-time two-way events.
The transport choice is secondary. The contract is what matters: schema, errors, idempotency, versioning, backward compatibility, deprecation policy.
Idempotency saves you from the real world
If you press the elevator button ten times, the elevator shouldn't arrive and leave ten times. It should understand the intent is one.
Idempotency means a repeated operation produces the same final effect. In networked systems, retries are inevitable: timeouts, retries, duplicate webhooks, worker restarts. If creating a payment, order, or message isn't idempotent, the system will eventually do something extra.
The architect designs idempotency at the contract level: idempotency key, unique constraints, safe retries, clear statuses.
Code gets rewritten. Data migrates for years. That's why the data model is one of the most expensive architectural decisions.
Data lives longer than applications
You can repaint a facade in a week. A foundation poured wrong reminds you of itself for the lifetime of the building.
The language, the framework, the UI may change several times. But tables, events, keys, relations, and historical records stay. A mistake in the data model often becomes a mistake in every future version of the product.
Normalization reduces duplication and the risk of drift. Denormalization speeds up reads and simplifies the read model. OLTP systems are optimised for transactions, OLAP for analytics. You can't design one model as if it will perfectly serve both classes of work.
Event sourcing is a strong tool, not a religion
A bank statement doesn't just store the current balance — it stores the history of operations. That's what lets you explain where the balance came from.
Event sourcing stores changes as a sequence of events and reconstructs current state from them. It's useful when history, audit, state recovery, and replay matter. The price is high: event schema evolution, query complexity, eventual consistency, demanding tooling.
CQRS separates the write model from the read model. It can dramatically simplify complex read systems, but it adds synchronisation and lag. Introducing CQRS just because "it sounds architectural" is an expensive way to turn one problem into two.
State is complexity that lives somewhere. The more copies of the truth, the more ways to be wrong.
Single source of truth doesn't mean single database
A company can have many reports, but there has to be one official payroll register. Otherwise payday turns into theatre.
Single source of truth means that for every important fact, you know where the authoritative version lives. A cache, a search index, a read replica, a materialized view — these are derived copies. They can be useful, but they shouldn't pretend to be the primary truth.
Stateful components hold state and demand care: transactions, locking, recovery, backup. Stateless components are easier to scale and replace, but they still depend on state living somewhere else.
A cache is a second truth that sometimes lies
The schedule on the fridge is convenient, until someone moves the meeting in the phone calendar.
A cache buys speed at the cost of freshness. The hardest cache question isn't "how to put things in," it's "when to invalidate." TTL, explicit invalidation, write-through, write-behind, cache-aside — these are different compromises between complexity, freshness, and load.
A race condition appears when two operations compete for state. Optimistic locking says: "conflicts are rare, we'll check the version at write time." Pessimistic locking says: "conflicts are dangerous, we'll lock up front." Both are right under different conditions.
Distribution solves problems of scale, but creates problems of time, order, and trust in the network.
The network isn't a wire, it's a source of uncertainty
A monolith is a conversation in one room. A distributed system is correspondence between people in different time zones — letters sometimes get lost, arrive twice, or run late.
In a distributed system, you can't just "call a function." Between services there's a network, timeouts, retries, partial failure, different clocks, different versions of code. What was a local transaction in the monolith becomes a coordination protocol.
The CAP theorem is often summarised badly. The practically useful version: during a network partition, you choose between consistency and availability. PACELC adds: even without a partition, you still choose between latency and consistency.
Consistency comes in flavours
Two people looking at the same Google Doc see the same thing almost instantly. Two people looking at a bank transfer can't settle for "almost."
Strong consistency gives you fresh truth, but costs latency and availability. Eventual consistency tolerates temporary drift, but often scales better. Causal consistency preserves cause-and-effect: if event B depends on A, B shouldn't become visible before A.
The saga pattern breaks a long business transaction into steps with compensating actions. Two-phase commit gives atomicity across resources, but is expensive and fragile in real distributed systems. The architect picks not "the strictest" model but the one sufficient for the risk.
Microservices don't fix bad design. They turn local problems into distributed ones.
The modular monolith is often underrated
One well-organised warehouse is faster than ten small ones if the same courier is driving between them anyway.
A monolith isn't an insult. A bad monolith is a tangle of dirty dependencies. A good modular monolith has strict internal boundaries, separate domains, explicit interfaces, and a single deployment unit. For a small team, it's often the best starting point.
Microservices help when you need independent releases, autonomous teams, different scaling profiles, failure isolation, or different technology stacks. The price: network calls, observability, distributed transactions, DevOps overhead, versioning, security between services.
A distributed monolith is the worst of both worlds
It's like living in separate apartments but walking next door for every spoon.
A distributed monolith looks like microservices, but the services aren't autonomous: shared database schema, synchronous call chains, releases that only ship together, changes that require touching everyone. The team pays the cost of distribution without getting the independence.
The Strangler Fig pattern lets you migrate carefully: wrap the old system, gradually extract capabilities, cut along real business boundaries, not along tables.
Sync couples systems in time. Async breaks that coupling, but brings delays, duplicates, and ordering complexity.
A phone call requires both sides to be free now. A letter can be read later — but it can get lost, run late, or demand a reply.
A synchronous call is easy to reason about: send, get an answer. But if the receiver is slow or unavailable, the sender suffers. Async via a queue or pub/sub lets you ride out failures and load spikes, but it demands a different mental model.
A queue usually distributes work across consumers. Pub/sub broadcasts an event to many subscribers. Kafka, RabbitMQ, SQS, Redis Streams — different tools with different ordering, durability, replay, and operational models.
Exactly-once is almost always marketing
If a letter is sent twice, decent accounting shouldn't pay the salary twice.
In practice you design for at-least-once delivery plus an idempotent consumer. A message can arrive twice; the handler has to survive it. A dead letter queue is for messages that couldn't be processed after a reasonable number of attempts.
Backpressure is the signal "the receiver can't keep up." Without it, the system gracefully accepts everything and then dies on the inside.
"Make it fast" isn't a requirement. A requirement sounds like latency, throughput, percentiles, and a load profile.
Average response time almost always lies
If nine people got their food in a minute and the tenth waited an hour, the average looks tolerable. The tenth disagrees.
Latency is the delay of a single operation. Throughput is how many operations the system handles per unit of time. Percentiles show the distribution: p50 is the median, p95 means 95% of requests are faster than that value, p99 is the tail.
The user doesn't feel the average — they feel the tail. Tail latency matters especially in systems where one screen depends on several backend calls: the probability of a slow response stacks up.
Profile before you optimise
Fixing performance without a profile is like treating a patient from a photo of their shoes.
Measure first, optimise second. N+1 queries, extra round trips, a bad index, serialisation, lock contention, GC pause, cold cache — they all look like "slow," but they're cured differently.
Amdahl's Law reminds you: speedup is bounded by the part of the system you actually optimise. Little's Law helps you think about queues: more latency at the same throughput means more work-in-progress sitting inside the system.
Scalability is the ability to grow in load and in features without rebuilding the system from scratch.
Vertical and horizontal scaling buy different things
You can buy one big truck. You can buy ten small ones. The first is simpler, the second is more flexible — but requires a dispatcher.
Vertical scaling means making one machine stronger. Simple, while there's headroom. Horizontal scaling means adding more instances. More flexible, but requires a stateless application layer, load balancing, a shared state strategy, and observability.
Databases scale harder than applications. Read replicas help reads, not writes. Sharding splits data but forces you to pick a shard key. A bad shard key turns scaling into a load imbalance.
Scaling features matters as much as scaling load
A city doesn't grow only by population. It grows by schools, hospitals, roads, and rules.
The system has to absorb not just more traffic but more product surface. If every new feature requires rewriting a shared God-service, the system doesn't scale organisationally.
The scaling cube is a useful model: X-axis is cloning, Y-axis is splitting by function, Z-axis is partitioning by data or tenants.
A reliable system isn't one where nothing breaks. A reliable system knows what to do when it does.
Retry without a strategy is an attack on yourself
If a door doesn't open, knocking once is reasonable. Knocking a thousand times a second is now a problem for the door and the neighbours.
Retry is for transient failures. But retries need a limit, a timeout, exponential backoff, and jitter. Otherwise a partial outage turns into a retry storm.
A circuit breaker temporarily stops calls to a stuck dependency. The bulkhead pattern isolates resources: if one downstream dies, it doesn't take all your worker threads and connection pools with it.
SLOs turn reliability into a contract
"We'll try our best" isn't a train schedule. A schedule says what counts as normal and what counts as a failure.
SLI is what you measure: success rate, latency, freshness. SLO is the target: 99.9% successful requests over 30 days. SLA is a promise to the customer with consequences attached.
The error budget tells you how much unreliability you're allowed to spend. If the budget is burned, the team stops chasing features and fixes reliability. That's the business-language version of engineering quality.
You can't add security right before release. It has to be built into the access model, the data, the infrastructure, and the processes.
Authentication and authorization are different things
A passport proves who you are. A ticket proves where you're allowed to go. One doesn't replace the other.
Authentication answers "who is this?". Authorization answers "what are they allowed to do?". Confusing them is dangerous: a user can be correctly logged in and still have no right to read someone else's invoice.
RBAC grants permissions through roles. ABAC considers attributes: resource owner, tenant, region, object state. Session-based auth is easier to revoke; JWT is easier to verify without a database, but harder to revoke. The choice depends on threats and lifecycle.
Threat modeling is professional paranoia
A good architect thinks like an attacker not because they distrust people, but because they trust reality.
STRIDE helps you look for threats: spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege. Defense in depth means several layers of protection: input validation, authz, encryption, audit log, rate limiting, least privilege.
Secrets management isn't "put the key in env and forget." You need to understand rotation, access, audit, blast radius, and what happens during a leak.
You can't fix what you can't see. The system has to explain its own state without archaeology in the code.
Monitoring tells you what's wrong. Observability helps you understand why
A "check engine" light is useful, but the mechanic still needs gauges, history, and diagnostic tools.
The three pillars of observability: logs, metrics, traces. Structured logging makes logs queryable. Metrics show aggregates. Distributed tracing follows a request's path through services.
A correlation ID is a small thing that saves nights: one request ID flows through gateway, service, queue, worker, and downstream.
Alert on symptoms
The user doesn't care that CPU is at 92%. They care that checkout doesn't work.
A good alert speaks user pain: error rate, latency, failed payments, stale data. A bad alert speaks of a cause that can be perfectly normal. If alerts are noisy, the team stops trusting them.
A runbook answers "what to do at 3 a.m." A post-mortem answers "how do we make sure this doesn't happen again." Blameless; the goal is to improve the system, not to find the guilty party.
An unrecorded architectural decision disappears together with the context of its author.
ADRs beat memory
An oral agreement is good until the first vacation, the first resignation, or the first argument six months later.
An Architecture Decision Record captures context, decision, alternatives, and consequences. An ADR doesn't have to be a novel. A good ADR answers: what problem were we solving, what did we choose, why didn't we choose the alternatives, when do we revisit.
Documentation isn't there for the audit — it's there for the next change. A new engineer has to understand not just "how" but "why."
A diagram is a working tool, not a decoration
A subway map doesn't show the wires or the bolts. It shows lines and transfers. That's enough not to get lost.
The C4 model gives you four levels: Context, Container, Component, Code. The first three are usually enough. A sequence diagram is useful when the order of interactions matters. Full UML is rarely needed; individual diagrams, yes.
Living documentation lives next to the code, updates in the PR, and gets reviewed. A document in a forgotten wiki quickly turns into historical fiction.
The architect talks to engineers, product, business, security, and legal. Each audience hears a different language.
Translate risk into the audience's language
A doctor doesn't only use Latin names with the patient. They explain what will hurt, how long the treatment is, and what to avoid.
You can say to an engineer: "we have no idempotency on the payment callback." The business needs to hear: "if the webhook retries, we may charge twice or ship the product twice; that's a financial and reputational risk."
Stakeholder mapping helps you see who cares about what: product wants time-to-market, security wants risk reduction, finance wants predictable cost, support wants understandable behaviour, engineering wants maintainability.
An RFC lowers the temperature of an argument
An argument at the whiteboard is often won by the loudest voice. A written proposal forces the arguments to stand apart from the voice.
An RFC describes the problem, the constraints, the options, the chosen solution, the risks, and the rollout plan. A good RFC invites criticism before the decision becomes policy.
Disagree and commit works only after an honest discussion. If the team wasn't heard, that isn't commit — that's suppression.
The architect is often still an individual contributor. Their authority comes from clarity of thinking, trust, and the ability to make the team stronger.
Influence without authority
A conductor doesn't play every instrument, but without one the orchestra quickly becomes a set of talented people playing different pieces.
The architect shouldn't become a bottleneck on every decision. Their job is to set principles, explain boundaries, grow people, and step in where the cost of a mistake is high.
Architect mentoring isn't "do as I do." It's teaching the questions: what alternatives have you seen, what did you give up, how will you test the risk, where does the responsibility end.
Delegating doesn't mean transferring ownership
A captain can hand off the wheel, but they can't say the course of the ship is no longer their problem.
Part of architectural decisions should be made by the teams. Otherwise the architect becomes a queue. But there have to be guardrails: principles, review, ADRs, platform constraints, quality gates.
The architect steps in when a decision is irreversible, breaks system invariants, creates security risk, or affects several teams.
Architecture only makes sense in the context of a business goal. Otherwise it's expensive engineering aesthetics.
Non-functional requirements are business requirements too
For a shop, "checkout works on Black Friday" isn't a technical detail — it's money.
Performance, availability, security, compliance, operability — these aren't "technical wants." They're product properties. The architect translates them into business impact: lost revenue, regulatory risk, support cost, speed of market launches.
Cost of delay helps you discuss not just the cost of doing the work, but the cost of waiting. Sometimes an architectural investment without immediate ROI is needed, because without it the next features start getting more expensive.
Build vs. buy isn't a matter of pride
Not every company should build its own power station just to turn the lights on.
Building gives you control and differentiation. Buying gives you speed and lowers operational load. Vendor lock-in is a real risk, but on its own it isn't an argument against buying. The question: how expensive is the exit if the vendor changes price, API, or quality?
The architect helps product see the capability map: which capabilities are the core of the business, and which are better bought.
When code is written by agents, the architect's value moves into specification, architectural thinking, and quality control.
Spec quality becomes the bottleneck
If the construction crew gets ten times faster, the binding constraint stops being the speed of bricks. It becomes the quality of the blueprints.
AI agents speed up implementation, but they don't remove architecture. A poorly framed task just turns into bad code faster. Specification-driven development means the primary artifact is the specification of behaviour, boundaries, invariants, tests, and acceptance criteria.
In an AI-native process, the architect writes less low-level code and more precise prose. They review the diff, the tests, the architectural boundaries, and the alignment with the spec.
Agent output deserves the same discipline as a human PR
A fast junior who writes a thousand lines an hour still needs review. Speed doesn't make code correct.
You can't accept agent code because it compiles. You need tests, evals, import boundaries, type checks, security review. Scenario evaluations matter especially: the system has to pass real cases, not just the happy path.
An AI-native organisation wins not where "everyone is vibe-coding," but where there are strong specifications, small iterations, automated checks, and architectural ownership.
The architect can be dangerous precisely because they sound convincing. Knowing the traps saves years.
Ivory tower architect
Someone draws a perfect city up on the hill but never walks down to see where people actually go.
The ivory tower architect makes decisions far from the code, the operations, and the team. Their diagrams are beautiful, but the implementation suffers. The cure is simple: read PRs, watch incidents, talk to engineers, walk the change path yourself.
Resume-driven development and cargo cult
Buying a fire truck because it impresses the neighbours is strange if you don't have water or firefighters.
Resume-driven development picks technologies for a line on the CV. Cargo cult engineering copies the shape of someone else's decision without the reason. NIH syndrome forces you to write your own where a mature external tool would do better.
Another trap is technical perfectionism. The perfect architecture that never reached the user loses to a good-enough system that ships and can evolve.
Architecture is an infinite game. Technologies change, but the ability to ask the right questions only gets stronger.
Learn from systems, not from hype
A cook grows not from watching knife ads, but from understanding ingredients, heat, time, and taste.
New technologies are worth studying through questions: what problem do they solve, what price do they introduce, where have they already failed, what are the alternatives, what has to be true for them to become useful.
T-shaped skills give you depth in one area and breadth across the neighbours. M-shaped skills appear in a mature architect: several deep pillars — data, distribution, security, product, AI tools.
Learning in public accelerates maturity
When you explain a decision in writing, the gaps in your thinking show up before production finds them.
Write ADRs, RFCs, engineering notes, post-mortems, short breakdowns of decisions. Learn from architects stronger than you — not just what they chose, but how they reasoned.
The architect people imitate usually isn't the one who knows the most terms. It's the person next to whom the team starts asking better questions.
- I can name the trade-offs of a decision without ego defence. - I understand where the source of truth lives in the system. - I tell reversible decisions from irreversible ones. - I can explain the architecture to engineering, product, and business in different words. - I write decisions so they can still be understood a year from now. - I don't hide complexity behind the words "best practice."
An architect is an engineer who learned to see the consequences before they became an incident.