Je krijgt een feature-verzoek. Een ticket misschien, of gewoon een Slack-bericht. Je opent je IDE, maakt een branch en begint te bouwen. Claude Code schrijft de code, jij reviewt, het gaat snel.
Dan, drie uur later, ontdek je dat je vijf architectuurkeuzes hebt gemaakt die je nooit bewust hebt gemaakt. De subscription-entiteit zit aan de User gekoppeld omdat Claude dat aannam. De tier-check zit in de controller omdat dat het makkelijkste paste. Er is geen audit trail omdat je nooit hebt gezegd dat je die nodig had.
De code werkt. Hij lost alleen niet het juiste probleem op.
Dit is geen Claude-probleem. Het is een ontwerpprobleem. Wanneer AI het coderen doet, wordt de ontwerpfase de hoogste-leverage activiteit die jij als developer kunt doen. Vage input levert vage code op. En toch is het precies de fase die de meeste developers overslaan.
Deze post gaat over hoe je dat aanpakt.
Waar je naartoe werkt
Aan het einde van een goede ontwerpfase heb je negen documenten die Claude Code — of elke developer — alles geven wat nodig is om te implementeren zonder te raden:
Wat je bouwt en waarom
- Problem statement — één alinea: het probleem, voor wie, waarom nu
- Acceptatiecriteria — in Given/When/Then-formaat; dit wordt ook de definitie van done voor Claude
- Out-of-scope — wat je bewust niét bouwt in deze iteratie
Hoe het in het systeem past
- ADR voor elke niet-triviale architectuurkeuze
- C4 Container-diagram — waar past dit onderdeel in het grotere systeem
- Sequence diagram voor de belangrijkste flow
Wat er gebouwd wordt
- API-contract — endpoints, request/response schema’s, foutcodes
- Data model — EF Core entiteiten en relaties
- Geordend implementatieplan met acceptatiecriteria per stap
- Testscenario’s — welke tests moeten slagen voordat het klaar is
Negen documenten klinkt als veel. Maar je schrijft ze niet vanuit het niets. Je produceert ze in vier gerichte Claude Code-sessies, waarbij elke sessie voortbouwt op de vorige.
Sessie 1: Probleemafbakening
Open je solution niet. Begin geen prompt met “bouw mij”. Begin hiermee:
I want to add a feature to our ASP.NET Core application.
Don't write any code yet. Don't propose a solution yet.
Ask me questions — one at a time — until you fully understand:
- What problem we're solving and for whom
- How often this situation occurs
- What "done" looks like from the user's perspective
- What we're explicitly NOT building in this iteration
When you have enough, write a one-page problem statement and ask me to confirm it.
Claude stelt vijf tot acht gerichte vragen. Niet generieke vragen als “wat is de scope?” — maar specifieke vragen die je dwingen te verwoorden wat je hebt aangenomen.
Voor een subscription tier-feature (Free / Pro / Enterprise met verschillende API-limieten) vraagt Claude bijvoorbeeld:
- Wat gebeurt er met een gebruiker die zijn limiet halverwege de maand bereikt — wordt hij meteen geblokkeerd of pas bij de volgende factuurperiode?
- Als een gebruiker downgradet, verliest hij dan direct toegang tot Pro-features of aan het einde van zijn huidige periode?
- Wie kan het abonnement van een gebruiker wijzigen — alleen de gebruiker zelf, of ook een admin?
- Hebben we een audit trail nodig van tierwijzigingen?
Dit zijn de beslissingen die de volledige implementatie bepalen. Ze beantwoorden vóórdat je code schrijft voorkomt dat je ze ontdekt tijdens een code review.
Na de vragen schrijft Claude een problem statement:
## Problem statement
Our ASP.NET Core API currently has no concept of subscription tiers.
All authenticated users have identical access to all endpoints and resources.
As we move toward a paid product, we need to differentiate access based on
subscription tier: Free, Pro, and Enterprise.
The primary need is rate limiting per tier (requests/minute) and feature
gating (certain endpoints only available to Pro and Enterprise).
Admins can change a user's tier at any time; the change takes effect immediately.
Downgraded users lose access to higher-tier features at the moment of downgrade.
We need an audit trail of all tier changes, including who made the change.
Out of scope: billing integration, payment processing, trial periods,
team/organization subscriptions.
Je leest het, corrigeert wat niet klopt, en bevestigt het. Dit kost vijftien minuten. Het voorkomt twee dagen rework.
Sessie 2: Architectuurverkenning en ADR
Je hebt een bevestigd problem statement. Open een nieuwe sessie — of ga door in dezelfde — en laad je codebase:
Read the solution structure. Here is the confirmed problem statement:
[plak problem statement]
Propose THREE different architectural approaches for implementing subscription
tiers. For each approach:
- Name the main components involved
- Explain how it fits (or conflicts) with our existing patterns
- List the trade-offs
Do not recommend one yet. I want to see the options first.
De “do not recommend yet”-instructie is belangrijk. Als je Claude vraagt om de beste aanpak, geeft het er één. Als je drie opties vraagt, zie je de afwegingen — en maak jij de keuze.
Voor subscription tiers in een typische ASP.NET Core API brengt Claude drie opties naar boven:
Optie A: Sla de tier op in de bestaande UserProfile-entiteit. Eenvoudig, geen extra join, maar mengt identiteits- en billing-concepten. Moeilijk later uit te breiden.
Optie B: Een aparte Subscription-entiteit met eigen tabel. Nette scheiding, ondersteunt geschiedenis, past bij een toekomstige billing-integratie. Één extra join per request.
Optie C: Een dedicated microservice of module met eigen database. Maximale scheiding, maximale complexiteit. Te zwaar voor de huidige scope.
Je kiest Optie B. Dan:
We're going with Option B — a separate Subscription entity.
Write an ADR documenting this decision. Include:
- Context: why we needed to make this decision
- Options considered: all three, with their trade-offs
- Decision: Option B and the reasoning
- Consequences: what becomes easier, what becomes harder
Save it as docs/adr/001-subscription-tier-storage.md
Claude produceert een echte ADR in minder dan een minuut. Iets wat voorheen drie uur schrijfwerk kostte, duurt nu dertig seconden prompten en vijf minuten reviewen.
De ADR is niet voor Claude. Hij is voor de developer — inclusief jij zelf over zes maanden — die moet begrijpen waarom deze keuze is gemaakt.
Sessie 3: Technisch ontwerp
Met de architectuurkeuze vast kun je de ontwerpdocumenten genereren. Dit zijn de artefacten die een developer nodig heeft om te bouwen zonder vragen te stellen.
API-contract:
Based on the ADR and problem statement, design the REST API contract
for subscription tier management.
Output a markdown table with: HTTP method, path, request body,
response body, HTTP status codes including errors.
Follow the existing patterns in our controllers/endpoints.
De output sluit direct aan op wat je gaat implementeren:
| Method | Pad | Request | Response | Status codes |
|---|---|---|---|---|
GET | /api/subscriptions/me | — | SubscriptionDto | 200, 401 |
PUT | /api/admin/users/{id}/subscription | UpdateSubscriptionRequest | SubscriptionDto | 200, 400, 401, 403, 404 |
GET | /api/admin/users/{id}/subscription/history | — | SubscriptionHistoryDto[] | 200, 401, 403, 404 |
Data model:
Design the EF Core entities needed for this feature.
Show the C# class definitions.
Include relationships with existing entities (User, UserProfile).
Add data annotations where appropriate.
Claude genereert de entiteiten met de juiste relaties, indexen en constraints — passend bij jouw bestaande conventies omdat het je codebase al heeft gelezen:
public class Subscription
{
public int Id { get; set; }
public int UserId { get; set; }
public SubscriptionTier Tier { get; set; }
public DateTime EffectiveFrom { get; set; }
public DateTime? EffectiveTo { get; set; }
public int ChangedByUserId { get; set; }
public string? ChangeReason { get; set; }
public User User { get; set; } = null!;
public User ChangedByUser { get; set; } = null!;
}
public enum SubscriptionTier
{
Free = 0,
Pro = 1,
Enterprise = 2
}
Sequence diagram:
Generate a Mermaid sequence diagram for the admin changing a user's subscription tier.
Include: HTTP client, API layer, authorization check, SubscriptionService,
repository, audit trail write, response.
sequenceDiagram
participant Client
participant API as SubscriptionsEndpoint
participant Auth as AuthorizationService
participant Svc as SubscriptionService
participant Repo as SubscriptionRepository
participant DB as Database
Client->>API: PUT /api/admin/users/42/subscription
API->>Auth: RequireRole("Admin")
Auth-->>API: Geautoriseerd
API->>Svc: UpdateTierAsync(userId: 42, tier: Pro, changedBy: adminId)
Svc->>Repo: GetCurrentAsync(userId: 42)
Repo-->>Svc: Subscription { Tier: Free }
Svc->>Repo: CloseCurrentAsync(subscription)
Svc->>Repo: CreateAsync(new Subscription { Tier: Pro, ... })
Repo->>DB: INSERT + UPDATE
DB-->>Repo: OK
Svc-->>API: SubscriptionDto
API-->>Client: 200 OK
Dit diagram gaat in de ADR of een apart ontwerpdocument. Het is het gesprek dat je vroeger op een whiteboard had, nu geproduceerd in zestig seconden en geversioneerd in je repository.
Sessie 4: Implementatieplan en testscenario’s
De laatste sessie produceert de documenten die de daadwerkelijke bouw aansturen:
Based on all the documents we've created — the problem statement, ADR,
API contract, data model, and sequence diagram — write an ordered
implementation plan.
Each step should:
- Be completable in one focused Claude Code session
- Build on the output of the previous step
- Have clear acceptance criteria
Then write five test scenarios (mix of unit and integration tests)
that must all pass before this feature is considered complete.
Het implementatieplan dat Claude produceert:
## Implementatieplan: Subscription tiers
### Stap 1: Data model en migratie
Maak Subscription-entiteit, SubscriptionTier enum en EF Core-migratie aan.
✓ Migratie draait zonder fouten
✓ Subscription-tabel aangemaakt met juiste kolommen en foreign keys
### Stap 2: Repository en service layer
Maak ISubscriptionRepository, SubscriptionRepository, ISubscriptionService,
SubscriptionService aan. Implementeer GetCurrentAsync en UpdateTierAsync.
✓ Unit tests slagen voor happy path en not-found-scenario
### Stap 3: API endpoints
Implementeer GET /api/subscriptions/me en PUT /api/admin/users/{id}/subscription.
Registreer endpoints in program.cs, voeg autorisatie-attributen toe.
✓ Endpoints retourneren correcte statuscodes
### Stap 4: Rate limiting middleware
Implementeer ISubscriptionTierProvider. Koppel aan bestaande rate limiting middleware.
✓ Free tier-gebruikers ontvangen 429 bij overschrijding van limiet
✓ Pro tier-gebruikers krijgen hogere limiet correct toegepast
### Stap 5: Integratietests
Schrijf integratietests met WebApplicationFactory voor alle drie endpoints.
✓ Alle vijf testscenario's slagen
✓ dotnet test eindigt met exitcode 0
Elke stap kun je direct als sessieprompt aan Claude Code meegeven. Het plan vervangt de mentale overhead van uitzoeken wat er als volgende moet — die beslissing is al genomen, in de ontwerpfase, toen het nog goedkoop was om te wijzigen.
Wat je Claude niét laat beslissen
Claude is uitstekend in het genereren van opties, het structureren van beslissingen en het produceren van documenten vanuit door jou gedefinieerde randvoorwaarden. Het is geen productmanager, compliance officer of teamlead.
Er zijn beslissingen die van jou moeten komen:
Businessprioriteiten. Wat wordt als eerste gebouwd, welke tier krijgt welke limieten, wat telt als een “Pro”-feature — dit zijn businessbeslissingen. Claude verzint plausibel klinkende antwoorden als jij ze niet aanlevert. Doe dat niet.
Security- en compliancevereisten. Als je product financiële gegevens, zorgdata of iets gereguleerds verwerkt, komen de vereisten niet uit Claudes trainingsdata. Ze komen van je juridische afdeling of compliancedocumentatie. Lever ze expliciet aan.
Performance-drempelwaarden. Vraag Claude “wat is een redelijke rate limit voor een free tier?” en je krijgt een getal. Dat getal is niet gebaseerd op jouw infrastructuur, jouw verkeerspatronen of jouw kostenmodel. Jij stelt de drempelwaarden in.
Teamconventies die niet gedocumenteerd zijn. Als je team patronen heeft die alleen in mensen zitten — niet in de codebase, niet in CLAUDE.md — weet Claude er niets van. Dit is de grootste bron van “technisch correct maar toch fout”-code. De ontwerpfase is een goed moment om die conventies boven water te halen en op te schrijven.
Wat je uiteindelijk hebt
Na vier sessies — samen twee tot drie uur — heb je:
- Een bevestigd problem statement
- Expliciete acceptatiecriteria met een out-of-scope definitie
- Een ADR die de belangrijkste architectuurkeuze documenteert
- Een API-contract in een markdown-tabel
- EF Core entity-definities
- Een Mermaid sequence diagram voor de hoofdflow
- Een geordend implementatieplan met criteria per stap
- Vijf testscenario’s die “klaar” definiëren
Dat is alles wat een developer nodig heeft om te bouwen zonder te raden. Inclusief jijzelf, volgende week, als je de helft van de beslissingen van deze week bent vergeten.
De volgende keer dat je een feature-verzoek krijgt: open geen IDE. Open een terminal. Start een Claude Code-sessie. Typ: “Schrijf nog geen code. Stel me vragen totdat je het probleem begrijpt.”
Wat je vroeger in je hoofd deed — of helemaal niet deed — doe je nu hardop met Claude. Het staat op papier. Het is besproken. En Claude weet wat het moet bouwen voordat het begint.
De ontwerpfase is geen overhead. Met AI is het het werk.