Specs for Engineers
A spec is a communication artifact. Its purpose is to give engineers the information they need to build the right thing without making them guess about product intent, edge cases, or scope boundaries. The best specs are the ones that engineers read once, ask a few clarifying questions about, and then build against with confidence. The worst specs are the ones that leave engineers making product decisions in code because the PM did not think things through.
This is a guide to writing specs that engineers actually find useful, written from the perspective of what engineers need, not what PMs like to write.
What Engineers Need
After working with hundreds of engineers, the pattern is clear. Engineers need six things from a spec, and almost nothing else.
1. Clear Requirements
A requirement is a statement about what the system must do, written in plain language. Not a user story. Not a business justification. A simple declaration of behavior.
Good requirements:
- The system sends a confirmation email within 60 seconds of
account creation.
- The search results page displays a maximum of 25 results per page.
- Users can upload files up to 50MB. Files larger than 50MB are
rejected with an error message.
- The export generates a CSV file with columns: date, user_email,
action, details.
- Session timeout is 30 minutes of inactivity. On timeout, the
user is redirected to the login page.
Bad requirements:
- The system should be fast. (How fast?)
- The search should return relevant results. (What is "relevant"?)
- The user experience should be intuitive. (Untestable.)
- We need to handle errors gracefully. (Which errors? How?)
Each requirement should be testable. If you cannot write a test for it, it is not a requirement. It is a wish.
2. Explicit Edge Cases
Edge cases are where most bugs live and where most specs fall short. Engineers think about edge cases naturally, but they should not have to make product decisions about them. That is the PM's job.
Feature: User can change their email address
Happy path:
User enters new email, receives verification link, clicks link,
email is updated.
Edge cases the spec must address:
- User enters an email that already belongs to another account.
What happens? (Reject with message? Merge accounts? Show a
different error?)
- User requests a change but never clicks the verification link.
How long is the link valid? What happens after expiration?
- User requests multiple email changes in quick succession.
Does each request invalidate the previous one?
- User changes their email while they have an active session on
another device. Are other sessions invalidated?
- User's new email is in a different domain. Does this affect
team membership or SSO?
- Email delivery fails (invalid address, mailbox full). How does
the user know? Is there a retry?
You do not need to solve every edge case in advance. But you need to identify them. Writing "TBD - discuss with engineering" next to an edge case is far better than not mentioning it at all.
Stripe's internal specs are famous for their edge case coverage. Every payment flow spec explicitly addresses what happens on timeout, retry, partial failure, and concurrent requests. This discipline is why Stripe's API behaves predictably even in unusual situations.
3. What Is NOT Included
This is the single most useful section of a spec and the one PMs skip most often. Engineers need to know the boundaries of what they are building so they do not over-build or make incorrect assumptions.
Feature: Team permissions
NOT included (explicitly):
- No cross-team permissions in this phase. Each team is isolated.
- No permission inheritance (child teams do not inherit parent
permissions).
- No audit trail in v1 (planned for v2).
- No API endpoint for permission management. Admin UI only.
- No granular permissions below the feature level (e.g., no
"can view but not edit" on individual records).
- No mobile support. Web only.
Without this section, an engineer might spend two days building permission inheritance because it "seemed like it should be included." That is two days wasted because the PM did not draw a clear boundary.
4. Performance Expectations
Engineers need to know what "fast enough" means. Without explicit performance requirements, every engineer applies their own standard, which leads to either over-engineering or under-engineering.
Performance requirements:
- Page load: first meaningful paint under 1.5 seconds on a
standard broadband connection.
- Search: results returned within 500ms for queries against
up to 100,000 records.
- File upload: progress indicator shown. Upload of a 50MB file
completes within 30 seconds on a 10Mbps connection.
- API response: p95 latency under 200ms for read endpoints,
under 500ms for write endpoints.
- Bulk operations: processing 500 records completes within
2 minutes. Progress is communicated to the user.
These numbers do not need to be exact, but they need to exist. "Fast" means different things to different engineers. "Under 500ms at p95" is unambiguous.
5. Data Model Implications
When a feature changes what data the system stores or how it relates to existing data, engineers need to know. They will figure out the schema themselves, but they need to know what the product expects the system to remember.
Data implications:
New data the system must store:
- Permission group: name, description, list of permissions,
list of assigned users, created_by, created_at
- Each user can belong to multiple permission groups
- Permission changes must be recorded: who changed what, when,
previous value, new value
Data relationships:
- A permission group belongs to one team
- A user can belong to multiple groups across different teams
- Deleting a group does not delete its members
Data retention:
- Permission change history retained for 2 years
- Deleted groups are soft-deleted (retained for 90 days)
This is not a database schema. It is a description of what the product needs to persist and how it relates conceptually. The engineer turns this into a schema. But they need the product intent to do it correctly.
6. What They Do NOT Need
Engineers do not want PMs telling them how to build things. Providing implementation details in a spec signals distrust and limits the engineer's ability to find better solutions.
Do NOT include in the spec:
- "Use React for the frontend." (Technology choice is engineering's
domain unless there's a business constraint.)
- "Store this in a PostgreSQL table with columns..." (The engineer
will design the schema.)
- "Use a background job queue for email sending." (The engineer
will decide the architecture.)
- "Cache the results for 5 minutes." (The engineer will determine
the caching strategy based on the performance requirements.)
- "Use a dropdown component for selection." (Unless the design
mockup specifies this. Even then, be open to alternatives.)
The exception is when there is a genuine business or product constraint on implementation. "The export must generate a standard CSV file because our customers import it into Excel" is a legitimate requirement. "Use the csv library in Python" is not.
Spec Format
There is no single correct format. Some teams use documents, some use tickets, some use wikis. The format matters less than the content. That said, here is a format that works well.
Spec: [Feature Name]
Author: [PM name]
Status: Draft / In Review / Final
Last updated: [date]
## Context
[2-3 sentences. Why are we building this?]
## Requirements
[Numbered list of specific, testable requirements]
## Edge Cases
[List of edge cases with product decisions for each]
## Not Included
[Explicit list of what this feature does NOT do]
## Performance
[Latency, throughput, and scale expectations]
## Data
[What the system needs to store, relationships, retention]
## Open Questions
[Things not yet decided, with owners and deadlines]
## References
[Links to mockups, PRD, research, technical spikes]
Writing for Clarity
Engineers read specs to extract information quickly. Every sentence should be unambiguous and every requirement should be independently understandable.
Ambiguous: "The system should support multiple file types."
Clear: "The system accepts JPG, PNG, WebP, and PDF files.
All other file types are rejected with the message
'Unsupported file type. Please upload a JPG, PNG,
WebP, or PDF file.'"
Ambiguous: "Users should be able to customize their dashboard."
Clear: "Users can add, remove, and rearrange widgets on their
dashboard. Available widgets: activity feed, metrics
summary, team calendar, recent documents. Maximum 8
widgets per dashboard. Default layout: activity feed
(top left), metrics summary (top right)."
Ambiguous: "Handle errors appropriately."
Clear: "On network timeout (>10s), show message: 'Connection
lost. Your changes are saved locally and will sync
when you reconnect.' Retry automatically every 30
seconds. After 5 failed retries, show: 'Unable to
connect. Please check your internet connection.'"
Collaborating on Specs
The best specs are not written by PMs in isolation. They are co-created through conversation.
Effective spec process:
1. PM writes first draft with requirements, scope, and known
edge cases (1-2 hours)
2. PM and engineering lead review together (30-60 minutes)
- Engineer identifies missed edge cases
- Engineer flags technical risks or constraints
- PM clarifies product intent where ambiguous
- Both identify open questions
3. PM updates spec based on discussion (30 minutes)
4. Design reviews for UX consistency (if applicable)
5. Final spec shared with full team before development begins
This process takes a few hours total and prevents weeks of rework. The 30-minute review with the engineering lead is the highest-leverage meeting in the entire product development cycle.
At Figma, specs go through a "crit" process where PMs, engineers, and designers review the spec together. This catches misalignment before code is written. The cost of finding a misunderstanding in a spec review is minutes. The cost of finding it after two weeks of development is days.
The Relationship Between PRD & Spec
A PRD and a spec are related but serve different audiences and purposes.
PRD:
Audience: Everyone (PM, design, engineering, stakeholders)
Focus: Problem, users, goals, scope
Detail level: Moderate
Changes: Relatively stable once development starts
Spec:
Audience: Engineering (and QA)
Focus: Requirements, edge cases, behavior, performance
Detail level: High
Changes: Evolves as design finalizes and edge cases are resolved
Some teams combine them into one document. This works for smaller features. For larger features, keeping them separate allows the PRD to stay concise while the spec goes into engineering-level detail.
Common Pitfalls
- Specifying the solution instead of the requirement. "Use a modal dialog" is a solution. "Show a confirmation before the user deletes their account" is a requirement. Let design and engineering choose the implementation.
- Missing the negative requirements. Specs that describe what the system does but never describe what it does not do. The "not included" section prevents scope creep and wasted effort.
- Assuming engineers will "figure out" the edge cases. They will figure them out in code, making product decisions on the fly. Sometimes they will guess right. Sometimes they will not. Specify the edge cases.
- Writing pixel-perfect design requirements before alignment on behavior. Getting agreement on what happens is more important than getting agreement on what it looks like. Behavior first, then visual design.
- Not updating the spec when decisions change. If sprint planning resolves an open question, update the spec. If scope is cut, update the spec. A stale spec is worse than no spec because it actively misleads.
- Over-specifying for small features. A one-day feature does not need a full spec. A verbal conversation and a well-written ticket may be sufficient. Match the formality to the complexity and risk.
Key Takeaways
Engineers need six things from a spec: clear requirements, explicit edge cases, what is not included, performance expectations, data model implications, and links to relevant references. They do not need implementation details, technology choices, or pixel-perfect designs before behavior is agreed upon. Write requirements that are specific and testable. Identify edge cases and make product decisions about them. Co-create specs with engineering through a review conversation. Keep the spec updated when decisions change. The goal is to give engineers the information they need to build the right thing with confidence.