rapidlaunchcode.app
Enterprise StarterAdvisoryEngineeringProductsWritingAbout
Book a call
rapidlaunchcode.app

Independent technology advisory and engineering. København, Denmark.

Njalsgade 21F, 2. sal, København

CVR 45 44 13 93

Nicklas@rapidlaunchcode.app

WhatsApp +45 31 33 25 99

Work

  • Enterprise Starter
  • Advisory
  • Engineering
  • Products
  • Contact

Resources

  • Writing
  • Guides
  • Free tools
  • About

Elsewhere

  • HourIQ
  • Translately
  • NomadWorld
  • Privacy

© 2026 Rapid Launch Code ApS. All rights reserved.

Built in København with Next.js, Contentful, and zero consultancy bullshit.

Back to guides
4 min · ARCHITECTURE

Architecture decisions that actually matter

Most architecture diagrams are decoration. Five decisions actually move the needle on cost, speed, and survivability. The rest is taste.

On this page
  • The five decisions that matter
  • The database choice (and the boring answer)
  • One deploy unit, until proven otherwise
  • Transactions and consistency
  • Background work and queues
  • Caching is debt with a hit rate
  • Integration boundaries (and the on-call story)
Updated 2026-04
TL;DR
  • Pick boring databases. Postgres covers 95% of cases for 5% of the operational cost.
  • Default to one deploy unit until production gives you a real reason to split.
  • Background work belongs in a table-backed queue before it belongs in a broker.
  • Caching layers are debt. Add them when measurements force you, not when a CV does.
  • The framework is rarely the decision that matters. The data model and the deploy boundary are.

The five decisions that matter

Most of what gets called architecture is actually preference. Five decisions genuinely shape the cost, speed, and lifespan of a system. Get these right and most other choices become recoverable. Get them wrong and no framework choice will save you.

  • The deploy unit. One service or many. This is a one-way door for years.
  • The data model. The shape of your tables determines what queries are cheap and what features are even possible.
  • The transaction boundary. What is allowed to be inconsistent, and for how long, and where the user sees it.
  • The integration boundary. Where you trust other systems and where you don't, and what you do when they're down.
  • The deletion plan. How you remove a piece of the system. If you can't answer this, you're collecting liabilities.

The database choice (and the boring answer)

For 95% of new systems, the right database is Postgres. It's not a fashion statement. It is, in 2026, the most under-used database among teams that still pick something else by default.

Postgres gives you transactions, joins, JSONB for the parts you actually want schemaless, partial indexes, materialized views, full-text search, listen/notify, row-level security, and a queue table that will outlast three of your microservices. The operational story is well-understood by every senior backend engineer in Europe.

Pick something else only when the workload genuinely doesn't fit: very high write throughput on time-series data (Timescale, Clickhouse), genuine document-store needs with no relational tail (MongoDB), real-time collaborative state (Convex), or vector search at scale (a dedicated index, not your primary store).

One deploy unit, until proven otherwise

The single most expensive architectural decision teams make is splitting a system into services before they have to. The microservices conversation belongs in its own essay, but the heuristic is simple: if you don't have multiple teams who own slices end-to-end, including on-call, you don't have the org for microservices.

A modular monolith with explicit module boundaries gives you 80% of the benefits people want from microservices, at 10% of the operational cost. When the day comes that you genuinely need to extract a service, you extract a module. The boundary is already there.

Boring is not the same as unsophisticated. Boring is what survives the engineer who picked it.

Transactions and consistency

Eventual consistency is not a free architectural feature. It is a UX problem you have moved off the database and onto the user. Every "the cart is empty for three seconds after I added something" is an architectural decision the user is paying for.

Default to strong consistency inside a single deploy unit. Reach for eventual consistency only when latency, scale, or geography genuinely demand it, and when product has agreed in writing that the inconsistency is acceptable in the user-facing flow.

Background work and queues

A queue table in your existing database is a serious primitive. SELECT FOR UPDATE SKIP LOCKED on Postgres handles tens of thousands of jobs per second on hardware that costs nothing. You get transactional enqueue with the rest of your write, no extra infrastructure, no second source of truth.

Reach for a real broker (Kafka, NATS, Pub/Sub, SQS) when you need fan-out to multiple independent consumers, when one queue would be a contention point across teams, or when you need replay semantics. Not before.

Caching is debt with a hit rate

Every cache layer you add is a new failure mode: stale reads, thundering herds, invalidation bugs, the cold-cache event when the cache fleet restarts. Add caching only when you have a measured latency or load problem, not because you read a blog post.

When you do add a cache, write the invalidation plan first. If you can't articulate when an entry is removed, your cache is a feature flag for serving wrong data.

Integration boundaries (and the on-call story)

Every external system you depend on becomes part of your uptime story. Stripe, your CRM, your CMS, your auth provider, your analytics — when they're down, you're down, unless you wrote the fallback.

  • Treat third-party calls as if they will time out, retry, double-fire, and rate-limit. Because they will.
  • Wrap them in a thin adapter so you can swap them or stub them in tests.
  • Decide explicitly what your app does when each one is unavailable. Write it down.
  • Cache the responses you can. Idempotency keys on the writes you can't.
What to actually do
  • Default to Postgres. Justify every other database with a measured workload constraint.
  • Default to a modular monolith. Extract services only when team structure forces it.
  • Use the database for queues and transactions until you outgrow it; you may never.
  • Make caching and eventual consistency explicit product decisions, not silent ones.
  • For every external integration, write down the failure plan before the happy path.

Want this kind of judgment on your project?

I read every email within one working day. Bring a project, a quote, or a system you're stuck on.

Book a 30-min callSee the Enterprise Starter
Related guides
  • 9 min

    15 things every Contentful enterprise project gets wrong in the first 6 weeks

    The 15 production gaps every enterprise Contentful + Next.js build hits in the first six weeks — and how to close each one without burning a sprint. A pre-kickoff checklist for technical leads on a Contentful enterprise starter.

  • 13 min

    REST + GraphQL hybrids for multi-locale CMS-driven sites

    Why neither REST-only nor GraphQL-only is the right call for an enterprise multi-locale CMS site, and how to split by concern instead. Includes the circular-reference problem on full REST payloads, the bundle cost of GraphQL on the client, the decision matrix per call site, the unified fetcher, granular cache tags, the block-as-fragment pattern, locale fallback in one round trip, Live Preview survival, Server Actions for CMA writes, the Algolia Sync API exception, and the migration sequence.

  • 3 min

    The consultancy playbook

    How digital consultancies operate, how they price, and where Danish clients typically overpay.