4 minute read Architecture

As systems grow more complex and teams become more distributed, architectural decisions become harder to make, and even harder to stick to. It’s one thing to choose a tech stack or design a service boundary; it’s another to ensure those decisions hold up over time and are understood (and followed) by the rest of the team.

In this post, we’ll walk through a practical, repeatable approach to making architectural decisions that are thoughtful, transparent, and resilient under change.

What Counts as an Architectural Decision?

Not every technical choice you make qualifies as architectural. Choosing whether to use tabs or spaces? Definitely not. But deciding between:

  • REST vs GraphQL
  • Monolith vs microservices
  • Shared database vs database per service
  • Event-driven vs request-response communication

These are architectural decisions, because they affect how the whole system is structured, and they’re costly to reverse.

Architectural decisions are the foundation your software is built on. That’s why they deserve care.

A Framework for Better Decisions

Here’s a five step process that helps technical teams not only make better decisions, but make them stick.

1. Identify the Decision Clearly

Start by explicitly stating what’s being decided. Write it down. That alone prevents scope creep and tangents.

Example: “Should we use an API gateway or let clients call services directly?”

Being clear about the decision helps everyone focus on the problem—not just the solution they already prefer.

2. Analyse Trade-Offs (Not Just Pros/Cons)

Architectural decisions are all about trade-offs. No approach is perfect, what matters is what’s appropriate.

Use a simple framework like this to compare options:

Criteria Option A (API Gateway) Option B (Direct Calls)
Complexity Adds another layer Simpler to implement
Security Centralised control Harder to manage consistently
Flexibility Easier to swap backends Clients tightly coupled
Observability Built-in monitoring/logging Requires per-client tooling

Involve stakeholders—engineers, product managers, and operations—to surface different perspectives and constraints. Discuss not just the technical pros and cons, but also how each choice impacts maintainability, scalability, and team workflows. This collaborative analysis uncovers hidden risks and ensures the decision is grounded in real-world needs, not just theoretical benefits.

3. Use ADRs to Document the Decision

ADRs (Architectural Decision Records) are short, markdown-style docs that capture:

  • The decision
  • The context
  • The options considered
  • The reasoning behind the choice
  • The consequences of the decision

Here’s a basic structure:

# ADR 004: Use API Gateway for External Requests

## Context
We need to expose internal services to external clients...

## Decision
We will use an API gateway (e.g. Kong or AWS API Gateway)...

## Alternatives
1. Let clients call services directly
2. Use BFF (Backend-for-Frontend)

## Consequences
- Additional infrastructure to manage
- Centralised point for throttling, auth, and logging

ADRs give your decisions longevity. They prevent repeated debates. They explain the “why” behind your architecture to new team members six months from now.

💡 Tip: Store ADRs in version control, right next to your code. This enables you to use pull requests for ADR reviews, so the team can discuss and approve architectural decisions just like code changes. Version control also provides a clear history of edits, making it easy to see how and why decisions have evolved over time.

4. Communicate Decisions Broadly

A decision isn’t done until it’s shared.

Post the ADR in Slack (or Teams 😬). Walk the team through it. Answer questions. Encourage feedback. Consider hosting short “architecture office hours” or design review sessions.

If you make a decision in a meeting but never share it, expect it to be forgotten or ignored.

5. Review and Revisit (But Don’t Flip-Flop)

Not all decisions are forever. Some should evolve. Others will be proven wrong. That’s okay.

The key is to revisit decisions intentionally, not impulsively.

Add a ‘Revisit By’ note in your ADRs when you know something is likely to change:

“Revisit after we reach 100k daily active users to assess scalability.”

But if nothing has changed in your context, resist the urge to constantly re-architect. Stability matters too.

Common Mistakes to Avoid

  • “Because the architect said so” – Authority is not an argument.
  • Chasing trends – Choose what’s right, not what’s hot.
  • Overthinking edge cases – Most systems die from underuse, not overcomplexity.
  • Skipping documentation – A decision no one remembers is no decision at all.

Real-World Example: To GraphQL or Not to GraphQL

In one project, we had to decide whether to expose internal data via REST or GraphQL. REST was simpler and familiar. GraphQL offered flexibility and fewer endpoints.

We wrote a quick ADR:

  • We chose GraphQL for external clients, REST internally.
  • Our reasoning: clients needed the flexibility, but our teams preferred REST internally for faster development and easier debugging.
  • We noted a consequence: increased complexity in authentication and rate-limiting.

That decision was referenced months later when we were debating whether to add REST for mobile clients. The ADR helped us stick to our original rationale, and saved us weeks of back-and-forth.

Final Thoughts

Good architectural decisions are context-aware, well-reasoned, and clearly communicated. Tools like ADRs don’t slow you down, they save you from future headaches.

In the end, architecture is a team sport. The goal isn’t perfection, it’s clarity, alignment, and adaptability.

Resources

Leave a comment