<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: guo king</title>
    <description>The latest articles on DEV Community by guo king (@guo_king_5d052f0d094fe6ca).</description>
    <link>https://dev.to/guo_king_5d052f0d094fe6ca</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3821717%2F7515d03c-5d13-4159-91db-fc69dd0d4446.png</url>
      <title>DEV Community: guo king</title>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guo_king_5d052f0d094fe6ca"/>
    <language>en</language>
    <item>
      <title>Why Your API Contract Breaks in Production (And How to Fix It in the Spec)</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Wed, 22 Apr 2026 08:11:48 +0000</pubDate>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca/why-your-api-contract-breaks-in-production-and-how-to-fix-it-in-the-spec-1kjh</link>
      <guid>https://dev.to/guo_king_5d052f0d094fe6ca/why-your-api-contract-breaks-in-production-and-how-to-fix-it-in-the-spec-1kjh</guid>
      <description>&lt;p&gt;The most expensive API bugs I've seen weren't implementation bugs. They were contract bugs — cases where the producer and consumer had different beliefs about what the API promised, and nobody wrote it down before the code was shipped.&lt;/p&gt;

&lt;p&gt;Here's the pattern: a team builds an endpoint, the frontend and backend agree on the behavior in a Slack thread or a meeting, and the implementation proceeds. Six months later, a field gets renamed as part of a "minor cleanup," a consumer breaks silently, and the incident postmortem includes the sentence "we thought this was backward compatible."&lt;/p&gt;

&lt;p&gt;The root cause is almost never malice or carelessness. It's that the contract was implicit — shared understanding that lived in people's heads rather than in a document that both sides could point to.&lt;/p&gt;




&lt;h2&gt;
  
  
  What an API contract actually is
&lt;/h2&gt;

&lt;p&gt;An API contract is the explicit agreement between a producer and its consumers about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What fields exist, what they're named, and what types they carry&lt;/li&gt;
&lt;li&gt;What the valid inputs are (required vs. optional, validation rules)&lt;/li&gt;
&lt;li&gt;What error codes mean and when each one is returned&lt;/li&gt;
&lt;li&gt;What "success" looks like at the HTTP level and the payload level&lt;/li&gt;
&lt;li&gt;What the retry behavior is — is this operation idempotent?&lt;/li&gt;
&lt;li&gt;What the version policy is — when does a change become breaking, and how much notice will consumers get?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most teams document some of these things. The ones that cause incidents are usually the last three.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three contract decisions teams skip
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Error taxonomy
&lt;/h3&gt;

&lt;p&gt;When an operation fails, what does the consumer do next?&lt;/p&gt;

&lt;p&gt;If your API returns &lt;code&gt;400&lt;/code&gt; for validation errors and &lt;code&gt;400&lt;/code&gt; for business-rule rejections, the consumer can't distinguish between "fix your input" and "this action is blocked for business reasons." They'll implement retry logic that retries unretryable errors, or they'll show the wrong message to the user.&lt;/p&gt;

&lt;p&gt;Before implementation, the spec should define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;400 Bad Request    — invalid input; client should fix and retry
409 Conflict       — valid input, business rule blocks; client should not retry
422 Unprocessable  — valid input, data state prevents action; may resolve over time
503 Unavailable    — transient; client should retry with backoff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a design decision. Make it in the spec, not in the error handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Idempotency
&lt;/h3&gt;

&lt;p&gt;Can the consumer safely retry this request if they don't get a response?&lt;/p&gt;

&lt;p&gt;Payment endpoints, state-mutation endpoints, and any operation with side effects need an explicit answer. "The backend should handle it" is not an answer — it's a deferred argument.&lt;/p&gt;

&lt;p&gt;Spec-first means writing this down before implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /orders
Idempotency: Yes
Key: X-Idempotency-Key header (UUID, client-generated)
Window: 24 hours — duplicate requests within 24h return the original response
After window: treated as new request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the consumer knows what to send, the backend knows what to store, and QA knows what to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Breaking change definition
&lt;/h3&gt;

&lt;p&gt;Before you ship your first external-facing version, agree on what counts as breaking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breaking (requires version bump, advance notice):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing a field&lt;/li&gt;
&lt;li&gt;Renaming a field&lt;/li&gt;
&lt;li&gt;Changing a field's type&lt;/li&gt;
&lt;li&gt;Changing the meaning of an existing status code&lt;/li&gt;
&lt;li&gt;Making an optional field required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-breaking (can ship without version bump):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a new optional field&lt;/li&gt;
&lt;li&gt;Adding a new endpoint&lt;/li&gt;
&lt;li&gt;Adding a new enum value (if consumers are built to handle unknown values)&lt;/li&gt;
&lt;li&gt;Bug fixes that bring behavior in line with documented behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Document this. When "minor cleanup" happens six months from now, the engineer making the change has a checklist, not a judgment call.&lt;/p&gt;




&lt;h2&gt;
  
  
  The OpenAPI to CI pipeline
&lt;/h2&gt;

&lt;p&gt;Once your contract is written, the best way to protect it is to make breaking changes fail in CI before they reach a reviewer.&lt;/p&gt;

&lt;p&gt;The minimal setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate OpenAPI spec from your implementation&lt;/strong&gt; (or write it first and validate against it)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run &lt;code&gt;openapi-diff&lt;/code&gt; or &lt;code&gt;oasdiff&lt;/code&gt; in CI&lt;/strong&gt; — fails the build if a breaking change is detected&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run contract tests against a real consumer&lt;/strong&gt; — Pact or equivalent; the consumer's expectations are versioned alongside the producer's spec&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This doesn't prevent all contract breaks. It prevents the ones that nobody caught because they were in a field rename that "obviously" wouldn't affect anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The spec-first version of this workflow
&lt;/h2&gt;

&lt;p&gt;The difference between spec-first API development and regular API development isn't the tools. It's the order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regular:&lt;/strong&gt; Build → Document → Ship → Break consumer → Fix&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spec-first:&lt;/strong&gt; Define contract → Review contract → Build to contract → Validate in CI → Ship&lt;/p&gt;

&lt;p&gt;The contract review is where most of the value lives. It's the moment when the consumer team can say "we rely on that field being optional" before the producer team has already built it as required.&lt;/p&gt;

&lt;p&gt;That conversation is almost free before implementation. It's expensive after deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  A minimal API contract template
&lt;/h2&gt;

&lt;p&gt;If you don't have a spec process yet, start with this for every new endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Endpoint: POST /v1/[resource]
Purpose: [one sentence]

Request:
  Required fields: [list]
  Optional fields: [list]
  Validation rules: [list]

Response (success):
  Status: 201
  Fields returned: [list]

Response (errors):
  400: [when, what to tell the consumer]
  409: [when, what to tell the consumer]
  503: [when, consumer should retry with backoff]

Idempotency: [yes/no] — if yes, key mechanism and window
Breaking change policy: [link to shared definition]
Version: v1 — changes that break the above require a new version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the minimum. It takes 15 minutes to write. The alternative is a 2am incident.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write about spec-first delivery and API contracts at &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;. The &lt;a href="https://spec-coding.dev/guides/api-contract-checklist" rel="noopener noreferrer"&gt;API Contract Checklist&lt;/a&gt; covers the full pre-release review process.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>programming</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>I Shipped Fewer Bugs After I Started Writing Specs. Heres the Framework</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Wed, 22 Apr 2026 08:11:29 +0000</pubDate>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-2p4f</link>
      <guid>https://dev.to/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-2p4f</guid>
      <description>&lt;h1&gt;
  
  
  I Shipped Fewer Bugs After I Started Writing Specs. Here's the Framework
&lt;/h1&gt;

&lt;p&gt;Last March, we had a billing incident that cost us three days. A rounding error in our invoice calculation was silently overcharging customers by fractions of a cent. Not enough for anyone to notice on a single invoice. But multiplied across thousands of transactions over two months, it added up. We had to issue refunds, write a post-mortem, and rebuild trust with a handful of enterprise customers who did the math.&lt;/p&gt;

&lt;p&gt;The fix took 20 minutes. The actual bug was a &lt;code&gt;Math.floor()&lt;/code&gt; where we needed &lt;code&gt;Math.round()&lt;/code&gt; with banker's rounding.&lt;/p&gt;

&lt;p&gt;Here's what stung: if anyone had written down "use banker's rounding for currency calculations" before writing the code, this never would have shipped. The developer who wrote it didn't know about our rounding convention. The reviewer didn't think to check. Nobody was wrong. The requirement just lived in one person's head and never made it to the keyboard.&lt;/p&gt;

&lt;p&gt;That incident changed how our team builds software.&lt;/p&gt;

&lt;h2&gt;
  
  
  What spec-first actually means
&lt;/h2&gt;

&lt;p&gt;Spec-first development is simple: before you write code, you write a short document describing what you're building, what you're not building, and how you'll know it works.&lt;/p&gt;

&lt;p&gt;It's not waterfall. It's not Big Design Up Front. It's 10 minutes of structured thinking in a text file before you open your editor. Think of it as a conversation with your future self and your reviewers, except you have it before you've sunk 8 hours into an implementation.&lt;/p&gt;

&lt;p&gt;The spec travels with the PR. It's a living artifact, not a bureaucratic gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: CRM contact deduplication
&lt;/h2&gt;

&lt;p&gt;One of our team members picked up a ticket to build contact deduplication for our internal CRM. On the surface, it seemed straightforward: find duplicate contacts, merge them. Here's the abbreviated spec she wrote before starting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Goal&lt;/span&gt;
Detect and merge duplicate contacts in the CRM based on email
and phone number matching.

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Fuzzy name matching (phase 2)
&lt;span class="p"&gt;-&lt;/span&gt; Automated merging without user confirmation
&lt;span class="p"&gt;-&lt;/span&gt; Deduplication of company records

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same email (case-insensitive) are flagged as duplicates
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same phone number (normalized to E.164) are flagged
&lt;span class="p"&gt;-&lt;/span&gt; User sees a side-by-side comparison and chooses which fields to keep
&lt;span class="p"&gt;-&lt;/span&gt; Merge preserves all activity history from both records
&lt;span class="p"&gt;-&lt;/span&gt; Merge is reversible for 30 days

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Contact A has email X, Contact B has email X and email Y.
  What happens to email Y after merge?
&lt;span class="p"&gt;-&lt;/span&gt; Three-way duplicates: A matches B, B matches C, but A doesn't match C
&lt;span class="p"&gt;-&lt;/span&gt; Contact with 500+ activities: does the merge UI choke?
&lt;span class="p"&gt;-&lt;/span&gt; Merged contact is referenced in active automation workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That spec took about 12 minutes to write. But look at what it caught before a single line of code was written:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The three-way duplicate problem.&lt;/strong&gt; Without the spec, the developer would have built a pairwise merge and discovered the transitive matching issue during QA. Or worse, in production when a user tried to merge a chain of duplicates and got inconsistent results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The automation workflow reference.&lt;/strong&gt; Contacts linked to active automations needed special handling. That requirement wasn't in the ticket. It came out of the developer thinking through edge cases while writing the spec. Without it, merging a contact mid-automation would have broken running workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reversibility requirement.&lt;/strong&gt; The original ticket said nothing about undo. But when you write "acceptance criteria," you start thinking about what happens when things go wrong. Thirty days of reversibility turned out to be a key requirement from the customer success team, and the developer discovered this during a quick spec review before starting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The template
&lt;/h2&gt;

&lt;p&gt;After six months of iteration, our team settled on a lightweight template. Here's the version we use for any feature that takes more than a couple of hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Feature: [Name]&lt;/span&gt;
&lt;span class="gs"&gt;**Author:**&lt;/span&gt; [Your name]
&lt;span class="gs"&gt;**Date:**&lt;/span&gt; [Today]
&lt;span class="gs"&gt;**Status:**&lt;/span&gt; Draft / In Review / Approved

&lt;span class="gu"&gt;## Goal&lt;/span&gt;
One paragraph. What are we building and why?

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
What are we explicitly NOT doing? (This prevents scope creep.)

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
Numbered list. How do we know this is done?

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
Bullet list. What weird inputs, states, or timing issues could break this?

&lt;span class="gu"&gt;## Rollout&lt;/span&gt;
How does this get to production? Feature flag? Percentage rollout?
Who monitors it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Five sections. One page. The non-goals section alone has saved us more rework than any other practice we've adopted. When someone suggests "hey, we should also handle X" during implementation, we check the non-goals list. If X is there, the answer is "not this PR." If it's not there and it should be, we update the spec and have that conversation before writing more code.&lt;/p&gt;

&lt;p&gt;I've published &lt;a href="https://spec-coding.dev/guides/spec-template-examples" rel="noopener noreferrer"&gt;the full template with examples&lt;/a&gt; if you want to grab it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six months of results
&lt;/h2&gt;

&lt;p&gt;We started using specs consistently in October 2025 across a team of eight engineers. Here's what changed by April 2026:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P1 incidents dropped from ~3/month to ~1/month.&lt;/strong&gt; Not all of that is attributable to specs. We also improved our CI pipeline. But the incidents we did have were operational (infrastructure, scaling) rather than "we built the wrong thing" or "we missed an edge case."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code review cycles got shorter.&lt;/strong&gt; Average time from PR open to merge went from 2.1 days to 1.4 days. Reviewers stopped asking "what is this supposed to do?" because the spec was right there. Reviews focused on implementation quality instead of requirements discovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Junior engineers ramped faster.&lt;/strong&gt; Two new hires in January were writing production specs within their second week. The specs gave them a structured way to demonstrate understanding before writing code, and gave senior engineers a concrete artifact to review instead of trying to evaluate whether someone "gets it" from a Slack conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope creep became visible.&lt;/strong&gt; When a feature grew beyond its original spec, we could point to the document and say "this is new scope. Do we want to update the spec or save it for a follow-up?" Before specs, scope crept silently until the PR was twice the expected size.&lt;/p&gt;

&lt;p&gt;The biggest surprise: specs made estimation better. When you force yourself to list acceptance criteria and edge cases upfront, you have a much clearer picture of the actual work. Our sprint velocity predictions got noticeably more accurate, not because we got better at estimating, but because we got better at understanding what we were estimating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;If you've never written a spec before, don't try to change your whole team overnight. Start with yourself, on one feature. Pick something you're about to build that has at least a couple of moving parts. Spend 10 minutes filling in the template above. Share it with whoever would review your PR and ask: "Does this match your understanding?"&lt;/p&gt;

&lt;p&gt;That one conversation will tell you whether spec-first development is worth adopting more broadly. In my experience, it always is.&lt;/p&gt;

&lt;p&gt;I've written a &lt;a href="https://spec-coding.dev/blog/what-is-spec-first-development-complete-guide" rel="noopener noreferrer"&gt;complete guide to spec-first development&lt;/a&gt; that covers the philosophy, the process, and the common objections. And the &lt;a href="https://spec-coding.dev/blog/how-to-write-technical-spec-template-guide" rel="noopener noreferrer"&gt;template is free to download&lt;/a&gt;. Take it, modify it, make it yours.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Daniel Marsh is a software engineer and the author of &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;, a resource for teams adopting spec-first development.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>agile</category>
      <category>engineering</category>
      <category>career</category>
    </item>
    <item>
      <title>10 Software Spec Mistakes That Cause Production Incidents (With Fixes)</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Wed, 22 Apr 2026 08:10:58 +0000</pubDate>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca/10-software-spec-mistakes-that-cause-production-incidents-with-fixes-34lk</link>
      <guid>https://dev.to/guo_king_5d052f0d094fe6ca/10-software-spec-mistakes-that-cause-production-incidents-with-fixes-34lk</guid>
      <description>&lt;p&gt;After 12 years in B2B SaaS — and too many postmortems — I've noticed that most production incidents trace back to a decision that wasn't made in the spec. Not a coding error. A specification gap.&lt;/p&gt;

&lt;p&gt;Here are the 10 mistakes I see most often, what the symptom looks like, and how to fix each one before implementation starts.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Acceptance criteria that can't be tested
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; QA closes the ticket as "passed" but the feature behaves differently than product expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The user should see a confirmation message after submitting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Given a valid form submission, when the user clicks Submit, then a green banner appears at the top of the page with the text "Your changes have been saved" and remains visible until the user navigates away or dismisses it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Acceptance criteria are a contract between product and QA. If QA has to ask the author what "confirmation" means, the spec didn't do its job.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Non-goals that don't name anything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Engineering builds something adjacent to the spec because the boundary wasn't explicit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Out of scope: internationalization and advanced settings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Out of scope for this release: (1) translated UI strings — English only; (2) per-user notification preferences — all users receive the same defaults; (3) bulk operations — only single-record edits are supported. A reviewer can reject this change if any of these appear in the implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The non-goal should be specific enough that a reviewer can use it to push back.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. No named decision owner
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Scope creep during implementation because nobody was authorized to say "that's out."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Every spec should have one named person who can approve scope changes. Not a committee. One person. If that person is unavailable, a named backup.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. "Handled elsewhere" for failure paths
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; An edge case hits production and ops discovers there's no fallback, no log, and no rollback path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Error handling will be managed by the existing error middleware.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Name the specific failure modes and what happens in each:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the payment processor times out after 10 seconds: return HTTP 503, log &lt;code&gt;payment.timeout&lt;/code&gt; with order ID, do NOT charge the card, surface "Payment unavailable — please try again" to the user. Do not retry automatically.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. Missing rollback definition
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; A deployment goes wrong and nobody agrees on what "rollback" means, so the incident runs 3x longer than it should.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Before implementation, answer: if this change is reverted, what exactly happens?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code revert only?&lt;/li&gt;
&lt;li&gt;Config flag flip?&lt;/li&gt;
&lt;li&gt;Database migration that needs to be reversed?&lt;/li&gt;
&lt;li&gt;Data that needs to be repaired?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If rollback requires data repair, that repair script should be written before the feature ships.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Acceptance criteria that only cover the happy path
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; QA testing passes 100%, but 3 edge cases surface in production week one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; For every main-flow scenario, write at least one failure scenario and one boundary scenario.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="err"&gt;Happy path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Given &lt;/span&gt;a valid user, when they submit, then success.
&lt;span class="err"&gt;Failure path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Given &lt;/span&gt;an expired session, when they submit, then redirect to login with the form state preserved in session.
&lt;span class="err"&gt;Boundary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Given &lt;/span&gt;a user with exactly 0 remaining credits, when they try to submit, then show the upgrade prompt before the form is processed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Ambiguous authorization rules
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; A user can access or modify something they shouldn't be able to. Or they can't do something they should be able to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only authorized users can edit this record.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Edit access requires: (1) the user is the record owner, OR (2) the user has the &lt;code&gt;admin&lt;/code&gt; role in the same organization. Users with &lt;code&gt;viewer&lt;/code&gt; role can read but not edit. Requests from users outside the record's organization are rejected with 403, regardless of their role.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. No stop-loss threshold for the release
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; A feature causes elevated error rates after deployment. Nobody knows whether to roll back or wait, so the on-call engineer makes a judgment call at 1am.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Name the threshold before the release:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Roll back automatically if: error rate on &lt;code&gt;/checkout&lt;/code&gt; exceeds 2% over a 5-minute window, OR payment processor timeout rate exceeds 5%, OR any P0 alert fires within 2 hours of deployment. The on-call engineer does not need approval to roll back if these thresholds are hit.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. "Friendly" or "reasonable" as a spec term
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Engineering and design interpret "friendly error message" differently. Or "reasonable performance" means 200ms to one person and 2 seconds to another.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Replace every vague term with a testable one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"friendly" -&amp;gt; specific message text or message category&lt;/li&gt;
&lt;li&gt;"reasonable" -&amp;gt; explicit metric with threshold&lt;/li&gt;
&lt;li&gt;"fast" -&amp;gt; p95 latency under X ms at Y concurrent users&lt;/li&gt;
&lt;li&gt;"handled" -&amp;gt; specific behavior enumerated&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  10. Spec written after the code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; The spec reads like documentation of what was built, not a description of what should be built. Nobody reviewed it before implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; This one is structural, not a wording fix. The spec needs to exist — and be reviewed — before implementation starts. The review is where the expensive conversations happen cheaply.&lt;/p&gt;

&lt;p&gt;The spec's job is not to describe decisions after they're made. It's to force decisions before they're expensive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The common thread
&lt;/h2&gt;

&lt;p&gt;Every mistake on this list has the same root cause: a decision that should have been made explicitly in the spec was left implicit, and the team discovered the gap somewhere more expensive — in review, in testing, or in production.&lt;/p&gt;

&lt;p&gt;Spec-first development doesn't mean longer documents. It means making the right decisions earlier, in writing, where they can be challenged before they're coded.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I publish practical spec-first guides and free templates at &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;. The &lt;a href="https://spec-coding.dev/guides/spec-review-checklist" rel="noopener noreferrer"&gt;Spec Review Checklist&lt;/a&gt; covers the pre-implementation review in detail.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>devops</category>
      <category>career</category>
    </item>
    <item>
      <title>I Shipped Fewer Bugs After I Started Writing Specs — Here's the Framework</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Wed, 01 Apr 2026 09:48:53 +0000</pubDate>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-4ll4</link>
      <guid>https://dev.to/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-4ll4</guid>
      <description>&lt;h1&gt;
  
  
  I Shipped Fewer Bugs After I Started Writing Specs — Here's the Framework
&lt;/h1&gt;

&lt;p&gt;Last March, we had a billing incident that cost us three days. A rounding error in our invoice calculation was silently overcharging customers by fractions of a cent. Not enough for anyone to notice on a single invoice — but multiplied across thousands of transactions over two months, it added up. We had to issue refunds, write a post-mortem, and rebuild trust with a handful of enterprise customers who did the math.&lt;/p&gt;

&lt;p&gt;The fix took 20 minutes. The actual bug was a &lt;code&gt;Math.floor()&lt;/code&gt; where we needed &lt;code&gt;Math.round()&lt;/code&gt; with banker's rounding.&lt;/p&gt;

&lt;p&gt;Here's what stung: if anyone had written down "use banker's rounding for currency calculations" before writing the code, this never would have shipped. The developer who wrote it didn't know about our rounding convention. The reviewer didn't think to check. Nobody was wrong — the requirement just lived in one person's head and never made it to the keyboard.&lt;/p&gt;

&lt;p&gt;That incident changed how our team builds software.&lt;/p&gt;

&lt;h2&gt;
  
  
  What spec-first actually means
&lt;/h2&gt;

&lt;p&gt;Spec-first development is simple: before you write code, you write a short document describing what you're building, what you're not building, and how you'll know it works.&lt;/p&gt;

&lt;p&gt;It's not waterfall. It's not Big Design Up Front. It's 10 minutes of structured thinking in a text file before you open your editor. Think of it as a conversation with your future self and your reviewers — except you have it before you've sunk 8 hours into an implementation.&lt;/p&gt;

&lt;p&gt;The spec travels with the PR. It's a living artifact, not a bureaucratic gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: CRM contact deduplication
&lt;/h2&gt;

&lt;p&gt;One of our team members picked up a ticket to build contact deduplication for our internal CRM. On the surface, it seemed straightforward: find duplicate contacts, merge them. Here's the abbreviated spec she wrote before starting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Goal&lt;/span&gt;
Detect and merge duplicate contacts in the CRM based on email
and phone number matching.

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Fuzzy name matching (phase 2)
&lt;span class="p"&gt;-&lt;/span&gt; Automated merging without user confirmation
&lt;span class="p"&gt;-&lt;/span&gt; Deduplication of company records

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same email (case-insensitive) are flagged as duplicates
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same phone number (normalized to E.164) are flagged
&lt;span class="p"&gt;-&lt;/span&gt; User sees a side-by-side comparison and chooses which fields to keep
&lt;span class="p"&gt;-&lt;/span&gt; Merge preserves all activity history from both records
&lt;span class="p"&gt;-&lt;/span&gt; Merge is reversible for 30 days

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Contact A has email X, Contact B has email X and email Y —
  what happens to email Y after merge?
&lt;span class="p"&gt;-&lt;/span&gt; Three-way duplicates: A matches B, B matches C, but A doesn't match C
&lt;span class="p"&gt;-&lt;/span&gt; Contact with 500+ activities — does the merge UI choke?
&lt;span class="p"&gt;-&lt;/span&gt; Merged contact is referenced in active automation workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That spec took about 12 minutes to write. But look at what it caught before a single line of code was written:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The three-way duplicate problem.&lt;/strong&gt; Without the spec, the developer would have built a pairwise merge and discovered the transitive matching issue during QA — or worse, in production when a user tried to merge a chain of duplicates and got inconsistent results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The automation workflow reference.&lt;/strong&gt; Contacts linked to active automations needed special handling. That requirement wasn't in the ticket. It came out of the developer thinking through edge cases while writing the spec. Without it, merging a contact mid-automation would have broken running workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reversibility requirement.&lt;/strong&gt; The original ticket said nothing about undo. But when you write "acceptance criteria," you start thinking about what happens when things go wrong. Thirty days of reversibility turned out to be a key requirement from the customer success team — the developer discovered this during a quick spec review before starting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The template
&lt;/h2&gt;

&lt;p&gt;After six months of iteration, our team settled on a lightweight template. Here's the version we use for any feature that takes more than a couple of hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Feature: [Name]&lt;/span&gt;
&lt;span class="gs"&gt;**Author:**&lt;/span&gt; [Your name]
&lt;span class="gs"&gt;**Date:**&lt;/span&gt; [Today]
&lt;span class="gs"&gt;**Status:**&lt;/span&gt; Draft / In Review / Approved

&lt;span class="gu"&gt;## Goal&lt;/span&gt;
One paragraph. What are we building and why?

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
What are we explicitly NOT doing? (This prevents scope creep.)

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
Numbered list. How do we know this is done?

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
Bullet list. What weird inputs, states, or timing issues could break this?

&lt;span class="gu"&gt;## Rollout&lt;/span&gt;
How does this get to production? Feature flag? Percentage rollout?
Who monitors it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Five sections. One page. The non-goals section alone has saved us more rework than any other practice we've adopted. When someone suggests "hey, we should also handle X" during implementation, we check the non-goals list. If X is there, the answer is "not this PR." If it's not there and it should be, we update the spec and have that conversation before writing more code.&lt;/p&gt;

&lt;p&gt;I've published &lt;a href="https://spec-coding.dev/guides/spec-template-examples" rel="noopener noreferrer"&gt;the full template with examples&lt;/a&gt; if you want to grab it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six months of results
&lt;/h2&gt;

&lt;p&gt;We started using specs consistently in October 2025 across a team of eight engineers. Here's what changed by April 2026:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P1 incidents dropped from ~3/month to ~1/month.&lt;/strong&gt; Not all of that is attributable to specs — we also improved our CI pipeline. But the incidents we did have were operational (infrastructure, scaling) rather than "we built the wrong thing" or "we missed an edge case."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code review cycles got shorter.&lt;/strong&gt; Average time from PR open to merge went from 2.1 days to 1.4 days. Reviewers stopped asking "what is this supposed to do?" because the spec was right there. Reviews focused on implementation quality instead of requirements discovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Junior engineers ramped faster.&lt;/strong&gt; Two new hires in January were writing production specs within their second week. The specs gave them a structured way to demonstrate understanding before writing code — and gave senior engineers a concrete artifact to review instead of trying to evaluate whether someone "gets it" from a Slack conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope creep became visible.&lt;/strong&gt; When a feature grew beyond its original spec, we could point to the document and say "this is new scope — do we want to update the spec or save it for a follow-up?" Before specs, scope crept silently until the PR was twice the expected size.&lt;/p&gt;

&lt;p&gt;The biggest surprise: specs made estimation better. When you force yourself to list acceptance criteria and edge cases upfront, you have a much clearer picture of the actual work. Our sprint velocity predictions got noticeably more accurate — not because we got better at estimating, but because we got better at understanding what we were estimating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;If you've never written a spec before, don't try to change your whole team overnight. Start with yourself, on one feature. Pick something you're about to build that has at least a couple of moving parts. Spend 10 minutes filling in the template above. Share it with whoever would review your PR and ask: "Does this match your understanding?"&lt;/p&gt;

&lt;p&gt;That one conversation will tell you whether spec-first development is worth adopting more broadly. In my experience, it always is.&lt;/p&gt;

&lt;p&gt;I've written a &lt;a href="https://spec-coding.dev/blog/what-is-spec-first-development-complete-guide" rel="noopener noreferrer"&gt;complete guide to spec-first development&lt;/a&gt; that covers the philosophy, the process, and the common objections. And the &lt;a href="https://spec-coding.dev/blog/software-spec-template-free-download" rel="noopener noreferrer"&gt;template is free to download&lt;/a&gt; — take it, modify it, make it yours.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Daniel Marsh is a software engineer and the author of &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;, a resource for teams adopting spec-first development.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>documentation</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>What Is Spec-First Development? (Complete Guide)</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Sat, 14 Mar 2026 02:43:23 +0000</pubDate>
      <link>https://dev.to/guo_king_5d052f0d094fe6ca/what-is-spec-first-development-complete-guide-41nd</link>
      <guid>https://dev.to/guo_king_5d052f0d094fe6ca/what-is-spec-first-development-complete-guide-41nd</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://spec-coding.dev/blog/what-i&amp;lt;br&amp;gt;%0A%20%20s-spec-first-development-complete-guide" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spec-first development becomes clearer when the team makes the &lt;strong&gt;hidden&lt;br&gt;
  decisions visible before coding starts&lt;/strong&gt;. This article focuses on those&lt;br&gt;
  decisions and why they matter in delivery.&lt;/p&gt;

&lt;p&gt;## 1. Why Teams Usually Get This Wrong&lt;/p&gt;

&lt;p&gt;The problem appears the moment more than one role depends on the answer.&lt;br&gt;
  Product wants speed, engineering wants boundaries, QA wants testability, and&lt;br&gt;
  operations wants something that can be rolled back without improvisation. If&lt;br&gt;
  the spec never resolves those tensions, the work moves downstream as rework.&lt;/p&gt;

&lt;p&gt;The real decision behind spec-first is &lt;strong&gt;ownership&lt;/strong&gt;. Who approves the&lt;br&gt;
  boundary? Who validates acceptance criteria? Who can stop a rollout? Without&lt;br&gt;
  those answers in writing, teams ship with blurred accountability.&lt;/p&gt;

&lt;p&gt;## 2. A Concrete Delivery Situation&lt;/p&gt;

&lt;p&gt;Test your spec against one realistic delivery path. Ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What can the reviewer &lt;strong&gt;reject&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What can the tester &lt;strong&gt;verify&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What can the operator &lt;strong&gt;roll back&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the document cannot answer those three angles, it is not ready. Stop asking&lt;br&gt;
   whether the team "understands the idea" and start asking whether the written&lt;br&gt;
  spec would survive handoff.&lt;/p&gt;

&lt;p&gt;## 3. What the Spec Needs to Say Out Loud&lt;/p&gt;

&lt;p&gt;A stronger spec is not longer by accident — it is more explicit exactly where&lt;br&gt;
  projects tend to drift. At minimum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The intended outcome, explicit &lt;strong&gt;non-goals&lt;/strong&gt;, and the decision owner for
scope changes&lt;/li&gt;
&lt;li&gt;Acceptance criteria that can be judged &lt;strong&gt;pass or fail&lt;/strong&gt; without tribal
knowledge&lt;/li&gt;
&lt;li&gt;Failure behavior, fallback paths, and which logs or metrics will surface
them after release&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 4. Acceptance Criteria That Remove Guesswork&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Given the approved scope and dependencies
When the team executes the primary flow
Then success can be verified with a concrete result and observable evidence&lt;/li&gt;
&lt;li&gt;Given an exception, retry, or permission boundary is hit
When the system takes the fallback path
Then the user-facing behavior and operational response remain explicit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to force every team into the same wording. The goal is to&lt;br&gt;
  force decisions about &lt;strong&gt;input, trigger, and expected behavior&lt;/strong&gt; while there is&lt;br&gt;
   still time to change course cheaply.&lt;/p&gt;

&lt;p&gt;## 5. Review Questions Before Implementation Starts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which decision would still be &lt;strong&gt;ambiguous&lt;/strong&gt; to a reviewer seeing the change
for the first time?&lt;/li&gt;
&lt;li&gt;Can QA derive the main-flow, failure-path, and regression cases &lt;strong&gt;without
interviewing the author&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;If the release fails, does the document tell operations what to watch and
when to stop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you cannot answer these without a side conversation, the draft is still&lt;br&gt;
  carrying unpriced uncertainty.&lt;/p&gt;

&lt;p&gt;## 6. Rollout, Monitoring, and Rollback&lt;/p&gt;

&lt;p&gt;Good specs do not stop at merge readiness. They tell the team how to release&lt;br&gt;
  safely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stage to the &lt;strong&gt;smallest useful audience&lt;/strong&gt; first — don't treat review
approval as a substitute for runtime evidence&lt;/li&gt;
&lt;li&gt;Name the &lt;strong&gt;stop-loss threshold&lt;/strong&gt; before release: error rate, latency, data
mismatch, or override volume&lt;/li&gt;
&lt;li&gt;Record what rollback actually means: code revert, config switch, job pause,
or data repair&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 7. Common Mistakes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treating scope as obvious and leaving the real policy decision for
implementation review&lt;/li&gt;
&lt;li&gt;Hiding risky edge behavior behind vague phrases like &lt;em&gt;reasonable&lt;/em&gt;,
&lt;em&gt;friendly&lt;/em&gt;, or &lt;em&gt;handled elsewhere&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Publishing a document that sounds complete but never states how success or
rollback will be judged&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 8. When to Go Deep vs. Stay Lightweight&lt;/p&gt;

&lt;p&gt;The right amount of detail is the amount that &lt;strong&gt;prevents expensive invention&lt;br&gt;
  later&lt;/strong&gt;. If a missing sentence would force engineering, QA, or operations to&lt;br&gt;
  guess — that sentence belongs in the spec.&lt;/p&gt;

&lt;p&gt;What matters is not document length. What matters is whether the document&lt;br&gt;
  prevents the team from rediscovering the same decision in implementation,&lt;br&gt;
  testing, and release review.&lt;/p&gt;

&lt;p&gt;## 9. Final Takeaway&lt;/p&gt;

&lt;p&gt;Spec-first development becomes easier once the spec names the risky decisions&lt;br&gt;
  early enough for someone to challenge them. That is the practical value:&lt;br&gt;
  &lt;strong&gt;less improvisation, fewer surprises in review, and cleaner evidence when it&lt;br&gt;
  is time to ship&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Daniel Marsh is a senior software engineer with 12 years of experience,&lt;br&gt;
  specializing in spec-first development. More articles at&lt;br&gt;
  &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
