SRS: The Technical Spec That Keeps Developers Honest
May 30, 2026 · 6 min read
Series: Understanding SDLC — Part 3 of 10
We’ve covered BRD (the business problem) and PRD (what we’re building). Now we get to the part developers actually care about: SRS — Software Requirements Specification.
If BRD is “why” and PRD is “what,” then SRS is “how, in excruciating detail.”
What Is SRS, Really?
SRS = the contract between product and engineering.
PRD says: “User searches leads by phone number, results show in <500ms"
SRS says: “API endpoint GET /leads?phone={number} queries PostgreSQL leads table with B-tree index on phone_number column, returns JSON array max 50 items, paginated, with HTTP 200 or 404 if not found.”
See the difference? PRD is readable by anyone. SRS is written for the people who write code.
Who reads SRS:
– Developers — write the actual code from this
– QA engineers — write test cases from acceptance criteria
– Tech lead — reviews for feasibility and consistency
– DevOps — provisions infrastructure based on non-functional requirements. (See also: Setting Up Claude Code.)
When Do You Write SRS?
The flow:
BRD (approved)
↓
PRD (approved)
↓
SRS (dev team writes)
↓
Code
SRS is written after PRD approval, before any code.
Why not code directly from PRD? Because PRD leaves ambiguity. “Fast search” could mean 2 seconds or 200 milliseconds. SRS removes that ambiguity with exact numbers, exact endpoints, exact database schemas.
Structure of a Good SRS
SRS is the most rigid document in SDLC. No room for interpretation. Here’s what it must contain:
1. Introduction & Scope
Brief context. What system, what version, what PRD this SRS references.
“This SRS defines technical requirements for Lead Automation System v1.0, referenced from PRD v1.2. Scope: backend API, dashboard frontend, WhatsApp Business API integration. Out of scope: mobile app, chatbot, automated email follow-up.”
2. Functional Requirements (FR)
Every feature, specified as testable statements. Use the format:
FR-01: The system shall accept incoming WhatsApp messages via Webhook and store them in the
leadstable within 10 seconds of receipt.
FR-02: The dashboard shall display leads in a paginated table (20 items per page) with columns: name, phone, source, timestamp, status.
FR-03: Users shall be able to filter leads by source (WhatsApp, Email, Web Form) and date range (default: last 30 days).
Each FR needs:
– Input (what triggers it)
– Process (what happens)
– Output (what the user sees)
– Error handling (what happens when it fails)
3. Non-Functional Requirements (NFR)
The invisible stuff that breaks production if you ignore it:
| Category | Requirement |
|---|---|
| **Performance** | API response time <200ms for 95th percentile |
| **Availability** | 99.5% uptime during business hours (08:00-20:00 WIB) |
| **Security** | All API endpoints require JWT authentication; rate limit 100 req/min per user |
| **Scalability** | System must handle 10,000 leads/month without performance degradation |
| **Data Retention** | Leads archived after 2 years; archived data queryable but read-only |
| **Compliance** | Phone numbers encrypted at rest (AES-256); comply with Indonesia data privacy law |
4. Database Schema
Actual table definitions:
Table: leads
- id (UUID, PK)
- phone_number (VARCHAR(20), indexed, encrypted)
- name (VARCHAR(100))
- source (ENUM: 'whatsapp', 'email', 'web_form')
- message_text (TEXT)
- status (ENUM: 'new', 'contacted', 'converted', 'archived')
- created_at (TIMESTAMP, default NOW())
- updated_at (TIMESTAMP)
5. API Specification
Endpoint-by-endpoint contract:
GET /api/v1/leads
- Query params: phone, source, date_from, date_to, page, limit
- Response: 200 OK + JSON array
- Response: 400 Bad Request (invalid params)
- Response: 401 Unauthorized (missing/invalid JWT)
- Response: 429 Too Many Requests (rate limit)
POST /api/v1/leads/{id}/status
- Body: { "status": "contacted" }
- Response: 200 OK + updated lead object
- Response: 404 Not Found (lead doesn't exist)
6. Acceptance Criteria
For every FR, define “done”:
AC-01: Given a WhatsApp message arrives, when the webhook fires, then the lead appears in the dashboard within 10 seconds.
AC-02: Given 10,000 leads in the database, when a user searches by phone number, then results display in <500ms.
AC-03: Given an unauthenticated request, when it hits any API endpoint, then the response is HTTP 401 with error message “Authentication required.”
Common SRS Mistakes
Wrong: Vague Requirements
Bad: “The system should be fast”
Good: “Dashboard page load time <2 seconds for 95th percentile with 10,000 leads"
“Fast” means nothing. “<2 seconds at 95th percentile" means QA can test it.
Wrong: Mixing How and What
Bad (what belongs in PRD): “User clicks the Export button and gets an Excel file”
Good (SRS): “GET /api/v1/leads/export returns .xlsx file, max 10,000 rows, generation timeout 30 seconds, download link valid 24 hours”
Wrong: No Error Handling
Every happy path needs a sad path:
– WhatsApp API down → queue message, retry 3x with exponential backoff
– Database connection lost → return HTTP 503, log error, alert on-call
– Rate limit exceeded → return HTTP 429 with Retry-After header
SRS vs PRD — Don’t Overlap
| Aspect | PRD | SRS |
|---|---|---|
| **Audience** | PM, Designer, Stakeholder | Developer, QA, DevOps |
| **Focus** | What the user experiences | How the system works technically |
| **Detail** | User stories, mockups, journeys | Database schema, API endpoints, error codes |
| **Metric** | User adoption, task completion | Response time, uptime, throughput |
| **Approval** | Before design starts | Before coding starts |
If your SRS contains user personas or Figma links, it’s bloated. If your PRD contains SQL queries or HTTP status codes, it’s premature.
When You Don’t Need SRS
SRS is overkill for:
– Bug fixes — ticket with repro steps is enough
– Minor UI tweaks — PRD + mockup is enough
– Internal tools with 1 user — PRD is enough
– Agile teams with strong communication — well-written user stories + acceptance criteria in Jira can replace formal SRS
But if:
– Budget >$20,000
– Timeline >2 months
– Team >3 developers + dedicated QA
– System has external integrations (APIs, third-party services)
– Compliance or security requirements exist
SRS is mandatory.
Closing
SRS is the developer’s insurance policy. A good SRS means:
– Developers know exactly what to build
– QA knows exactly what to test
– DevOps knows exactly what to provision
– Nobody can say “that’s not what I meant” after code is written
It takes time to write. But it saves more time in arguments, rework, and production fires.
Next post: System Design Document — the architecture blueprint that shows how all the pieces fit together.
Series: “Understanding SDLC” — Part 3 of 10. Follow at [susiloharjo.web.id](https://susiloharjo.web.id)
Discover more from Susiloharjo
Subscribe to get the latest posts sent to your email.