What to Get Right in the First Six Months

by Umar Farooq Khawaja, Founder / Lead Developer

What to Get Right in the First Six Months

“The best architects don’t build perfect systems—they build systems that can evolve.”

In software development, there’s a persistent myth that success hinges on getting every decision right from day one. The truth? Early decisions don’t need to be perfect — they need to be directionally correct, visible, and easy to change.

The first six months are not about locking in forever; they’re about establishing momentum, exposing hidden assumptions, and building feedback loops that let the system learn as it grows. Getting this phase right means trading certainty for agility—anchoring in principles, not specifics.

Let’s break down three pivotal practices that set high-performing teams apart in those early months.

1. Decide What “Done” Means

Ambiguity around quality, ownership, and operational readiness is the silent killer of velocity. It shows up as late-night hotfixes, duplicated effort, and teams tiptoeing around “the legacy code” they helped write six weeks prior.

Why it matters

If “done” means “compiles and passes unit tests” to one engineer—but “fully documented, observable in production, and owned end-to-end by a single team” to another—you’ve outsourced coordination costs to chaos. Repeatedly.

How to do it right

Define release quality, ownership, and operational expectations early—even if they evolve quickly.

AreaClarify Early
Release QualityWhat’s non-negotiable? (e.g., “All public endpoints must have metrics, alerts, and rollback capability”)
OwnershipWho is on-call for what? Who decides when a change is safe to ship?
Operational ExpectationsMonitoring cadence? Logging level? How do we measure reliability (SLOs/SLAs)?

💡 Top Tip

A good foundation is not “more architecture”. It is reducing uncertainty: clear ownership, a reliable delivery path, and constraints people can follow.

For example:

  • Release quality: Every service must expose /health with status + version, log all uncaught errors to central logging, and be deployable via CI/CD in under 5 minutes.
  • Ownership: Each service has one named “tech lead” accountable for quality, but no single person owns decisions—decisions are made in rotating design reviews.
  • Operational expectations: MTTR < 30 min for P1s; SLO = 99.9% availability measured weekly.

This isn’t over-engineering. It’s risk mitigation through visibility.

Vertical slice of a working feature
A vertical slice makes “done” visible — auth, API layer, storage, and observability all in one small flow.

2. Build a Thin Vertical Slice

Architecture debates often stall before the first line of code is written. Teams argue over microservices vs. monoliths while user needs gather dust.

A thin vertical slice—a tiny but complete end-to-end feature (e.g., “As a user, I can sign up and see my profile”)—cuts through the noise.

Why it works

It forces conversations in context, not in abstraction:

  • Does auth integrate with our identity provider?
  • Is error handling consistent across layers?
  • Can we deploy this? Monitor it? Roll back safely?

You don’t get these insights from UML diagrams. You get them by shipping something small and measuring how it feels—for users and engineers alike.

How to do it right

  1. Pick the simplest path through your system that delivers real value (even if it’s 80% fake data).
  2. Include all layers: frontend, API, auth, database, logging, monitoring, deployment.
  3. Ship it early and often. Even to just yourself first.

✅ Do: “User signs up → email is sent → profile page shows (even if empty) → metrics fire → deploy via single CLI command.”

❌ Don’t: Build the entire user database schema + auth module + email service + audit logging before verifying the core loop works.

This slice becomes your anchor point—a reference implementation, a “test double” for design discussions, and proof that directionally correct can be shippable.

Directionally correct: small, observable, and reversible
A thin slice is directionally correct—not perfect, but demonstrably aligned with goals and easy to iterate on.

3. Leave the Door Open

The biggest risk in early development isn’t building too little—it’s building too much that can’t be un-built. Speculative abstractions, “just-in-case” modules, and premature integrations lock you into decisions before you have data.

Why it matters

When every change requires touching a dozen “generic” services, teams move slower. They avoid refactors, accumulate technical debt in the name of consistency—and soon, your architecture isn’t scalable—it’s inert.

“Scalability” isn’t about scale—it’s about adaptability. The ability to pivot when reality contradicts assumptions.

How to do it right

  • Avoid speculative abstraction. If no one’s used it yet, don’t design for three consumers. Design for one, and make the interface obvious when a second consumer arrives.
  • Prefer simple structure with explicit interfaces. A single service with clear method signatures is easier to evolve than 20 loosely coupled services with undefined contracts.
  • Build for additive change, not destructive refactors. When new requirements emerge, can you add behavior without modifying existing code?

For example: Instead of a “notifications engine” with pluggable providers on Day 1, start with:

def send_email(to, subject, body):
    # hardcode SMTP for now

Then when SMS is needed in Month 3? Add:

def send_sms(to, message):
    ...

—no rewrites. Just addition.

This doesn’t mean “don’t plan.” It means plan backward from constraints, not forward from speculation. Let the first six months be your discovery phase—not your final spec.

The First Six Months: A Launchpad, Not a Foundation

You’re not building a cathedral here. You’re launching a raft down a fast-moving river—you need to move quickly, test currents, and adjust course constantly.

Getting these three things right—clarity of “done,” vertical velocity, and open architecture—means your first six months won’t be wasted time. They’ll be the foundation for a system that grows with understanding, not against it.

Because in software, the best decisions aren’t made in meetings—they’re proven in production.


Want more practical systems thinking? Subscribe for essays on operability, resilience, and engineering velocity.

More articles

Durability by Design

The goal isn’t to avoid change. The goal is to make change routine, safe, and cheap — for years.

Read more

Restraint Is What Enables Fast Iteration

Teams that iterate quickly are often the ones that say ‘no’ early — to complexity, to optional features, and to premature generality.

Read more

Tell us about your project

Our availability

  • London
    United Kingdom 🇬🇧
  • Birmingham
    United Kingdom 🇬🇧
  • Manchester
    United Kingdom 🇬🇧