DEV Community

Jordan Huang
Jordan Huang

Posted on

Your Chat Log Is Not an ADR

Did your last stack choice live inside a chat window?

I keep finding architecture calls trapped in assistant threads lately. Nobody wrote an ADR. Nobody ran a killing spike.

That pattern is not a design process at all. It is only a colorful transcript of guesses.

This FAQ attacks five claims I still hear weekly. Each myth gets evidence you can check. Then I give a corrected mental model.

I also include a spike harness you can copy. Treat every command as a proposed workflow. I am not citing private production numbers here.

What problem are we actually solving?

Generated code arrives painfully fast these days. Durable decisions still arrive late, if ever.

A model can sketch a service in minutes. It still cannot own your failure domain.

Who pages when the queue finally backs up? Who pays the surprising storage bill later?

Those questions never appear in a cheerful chat summary. Speed of code is not speed of judgment.

Where a free model actually helps

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

I reach for MonkeyCode when a spike needs a free model pass. I also park short experiments on its free server option. That is the only product role in this workflow.

Swap those tools and the checklist still holds. The checklist is the point, not the vendor.

Myth 1: The model chose the stack for us

Did the model really accept production risk with you?

A model completes tokens against your current prompt. It never signs the on-call rotation afterward.

It never files the incident report next month. It never explains the invoice to finance.

Claim developers repeat: the assistant picked Postgres, so we should.

What you can observe: a plausible paragraph plus a compose sketch.

Corrected mental model: you chose; the model only autocomplete-argued.

Write the choice on a tiny card today. Name the rejected options in public too.

Decision: store order snapshots in Postgres.
Rejected: SQLite for multi-instance writers.
Rejected: a document store we do not operate.
Owner: replace-with-a-human
Review: 30 days after first real traffic.
Enter fullscreen mode Exit fullscreen mode

If you cannot fill that card honestly, you still do not have a decision. You have a vibe with YAML attached.

Myth 2: A generated diagram equals architecture

Can a mermaid chart page anyone at three in the morning?

I have watched models emit confident sequence diagrams for brownfield work. Then the running code ignored every arrow they drew.

Claim: we have architecture because the chart looks complete.

Evidence check: diff the diagram against real runtime paths.

Corrected mental model: a diagram is a hypothesis you must trace.

Proposed probe, not a production recipe:

# labeled example — run only on throwaway code
python3 -m http.server 8765 &
curl -sS -D - http://127.0.0.1:8765/ -o /dev/null
ss -ltnp | grep 8765 || netstat -ltnp | grep 8765
Enter fullscreen mode Exit fullscreen mode

Does the real handler match the picture today? If not, the picture is fan fiction.

Ask the model to list every assumed hop. Then delete each hop you cannot curl.

Assumed hops:
- client -> API
- API -> worker
- worker -> snapshot table
Delete any hop with no request, log, or test.
Enter fullscreen mode Exit fullscreen mode

Architecture is the path you can exercise. Everything else is illustration.

Myth 3: The free server already proved the design

What did that scratch process actually prove for you?

Running generated code on a free server answers one narrow question. The happy path did not crash this morning.

It does not prove multi-tenant isolation under real load. It does not prove a backup restore you never rehearsed.

Claim: it ran on the free server, so the design is sound.

Evidence: one process, one user, one unmeasured dataset.

I will not invent hardware details or quota numbers here. I do not have verified product figures to quote.

Corrected mental model: treat the free server as a scratch pad only. Promote only what you re-run under your constraints.

Decision table I actually fill during a spike:

Question Spike answer Still unknown
Does the API boot? yes / no process limits
Can two writers collide? untested locking story
What fails closed? untested authz defaults
How do we migrate? untested backup owner
Can we restore one row? untested drill date

Empty cells are the architecture, not the boot log. Green logs hide the questions you skipped.

Ask yourself who owns each empty cell. If the owner is "the model," the cell is still empty.

Myth 4: More alternatives mean a better choice

Does option soup ever kill a bad design in time?

Models love listing five patterns and a polite shrug. That list is not an evaluation.

Claim: we evaluated Kafka, queues, and the database already.

Evidence: three paragraphs, zero load, zero failure injection.

Corrected mental model: two alternatives, one spike each, one kill criterion.

Kill criteria I write before anyone generates code:

Kill Redis if we need disk-backed replay.
Kill the cron if we need sub-minute delivery.
Kill the monolith if two teams must ship daily.
Kill SQLite if two processes write at once.
Enter fullscreen mode Exit fullscreen mode

If nothing can kill a candidate, you are collecting vibes. Vibes do not survive the first incident.

Use the free model to draft kill criteria first. Do not ask it to crown a winner. Then implement the smallest spike that can actually die.

A dead spike is a successful architecture day. A pretty winner with no kill test is risk.

Myth 5: The chat summary is already the ADR

Would you treat a mutable thread as append-only truth?

People paste the last assistant message into Confluence weekly. They call that paste documentation and walk away.

Claim: the thread explains why we built it this way.

Evidence: the same thread contains abandoned stacks and steered opinions.

Chat is not append-only truth you can audit later. You can nudge it into convenient amnesia.

Corrected mental model: an ADR is dated, owned, and hard to rewrite. Chat remains a scratch buffer.

Minimal ADR skeleton:

# ADR-0014: Snapshot orders in Postgres

Status: accepted
Date: 2026-09-04
Deciders: replace-with-real-owners

Context:
We need durable order snapshots after payment.

Decision:
Postgres table `order_snapshot` with idempotent upserts.

Consequences:
- We own migrations and backups.
- We reject SQLite for concurrent writers.
- We will revisit after the first restore drill.

Spike evidence:
- Boot check: see `spike/Makefile`
- Collision check: still open
Enter fullscreen mode Exit fullscreen mode

Notice the open collision item still sitting there. Open items keep the record honest.

If the ADR cannot name a human owner, it is still a chat log. Publish it anyway, then assign the owner.

Artifact: a falsifiable spike workflow

Here is the workflow I want on generated services. It is a proposal, so run it on throwaway code only.

Step 1. Freeze one question

Write one sentence. Keep it under twelve words.

Can two workers upsert the same order without double charge?
Enter fullscreen mode Exit fullscreen mode

If your question needs a comma, you asked two questions. Split the card before you prompt anything.

Step 2. Write kill criteria before any code

FAIL if a second upsert creates a second row.
FAIL if the handler returns 200 with no write.
FAIL if we cannot restart and read the row.
Enter fullscreen mode Exit fullscreen mode

Pin those lines in the branch README. Do not hide them inside the prompt history.

Step 3. Ask a free model for one file

Do not ask for a platform. Ask for a single file.

Prompt shape I actually type:

Write a single Python file.
It exposes POST /orders/{id}/snapshot
It upserts into SQLite for the spike.
Include a second request that must not duplicate.
No framework. No Docker. No extra services.
Enter fullscreen mode Exit fullscreen mode

Keep the output on a throwaway branch. Review it like a stranger sent the patch.

Step 4. Execute on a scratch server

Use a free server option for the process. Your laptop works if the spike is local.

# proposed commands — verify on your machine
python3 -m venv .venv
. .venv/bin/activate
pip install -q pytest
python3 spike_upsert.py &
sleep 1
curl -sS -X POST http://127.0.0.1:8000/orders/abc/snapshot
curl -sS -X POST http://127.0.0.1:8000/orders/abc/snapshot
pytest -q test_spike_upsert.py
Enter fullscreen mode Exit fullscreen mode

I am not publishing timings against someone else's clock. Timing without your own clock is theater.

Step 5. Record the table, then lock the ADR

Copy the decision table into the record. Fill unknowns in public, not in chat.

Then freeze the ADR. Stop editing the assistant thread for history.

Tiny test you can paste

This example is labeled and not executed here.

# test_spike_upsert.py — proposed, not executed in this article
def test_second_post_does_not_duplicate(client):
    r1 = client.post("/orders/abc/snapshot")
    r2 = client.post("/orders/abc/snapshot")
    assert r1.status_code in (200, 201)
    assert r2.status_code in (200, 201)
    assert count_rows("abc") == 1
Enter fullscreen mode Exit fullscreen mode

If that test does not exist, you do not have a spike. You only have a demo that smiled once.

Makefile I keep beside the ADR

Proposed file. Adjust ports after you read it.

# spike/Makefile — proposed
.PHONY: spike adr-check

spike:
    python3 spike_upsert.py &
    sleep 1
    curl -sf -X POST http://127.0.0.1:8000/orders/abc/snapshot
    curl -sf -X POST http://127.0.0.1:8000/orders/abc/snapshot
    pytest -q test_spike_upsert.py

adr-check:
    @test -f ADR-0014.md
    @grep -q "Collision check" ADR-0014.md
Enter fullscreen mode Exit fullscreen mode

Run make spike before you argue in standup. Arguments without a failing test are theater.

Run make adr-check before you merge the branch. Missing files mean the chat still owns the design.

What this workflow refuses to be

This is not capacity planning for a holiday sale. This is not a security review of authz.

This is not permission to skip human reviewers. This is not production traffic on a scratch box.

Free model output can be wrong in confident English. Free servers are not your region, your IAM, or your data.

Do not store customer records on a scratch box. Do not paste secrets into any prompt.

A passing spike does not freeze dependency risk. Re-read the lockfile after the ADR is accepted.

Who should skip this approach

Skip this if a working architecture guild already owns ADRs.

Skip this if the change is a one-line bugfix with tests.

Skip this if nobody will own backups after merge.

Skip this for safety-critical systems that need a review board.

Also skip this if you cannot name a kill criterion. You are not ready to prompt yet.

Mental model worth keeping

The model proposes. The spike falsifies. The ADR decides.

Chat stays cheap. Reversal stays expensive for months.

Would you merge a stack that cannot fail a test? Why merge a stack that never sat one?

If you run one spike this week, keep the kill criteria. That list is the architecture talking back.

Top comments (0)