Imagine: a development team spends three months building features, only to discover at acceptance that the client meant something entirely different. Without a detailed Software Requirements Specification (SRS), such discrepancies are the norm. We know this firsthand: after years working on web projects, we have seen dozens of cases where the lack of clear requirements extended timelines by 40% or more. SRS is a key piece of software documentation that saves money and nerves. It turns "I want it like Google" into measurable technical characteristics understandable to both developer and client. Without it, rework risk increases 2–3 times and the budget grows by 30–50%.
Why SRS Is the Only Way to Avoid Rework
A requirements specification is the single source of truth for the team. It synchronizes expectations of the client, developers, and QA, eliminating misunderstandings. Result: less rework, stable budget, and predictable timelines. Requirements management is our core process, refined over years.
How to Classify Requirements Correctly
Requirements fall into three categories, and it is important not to confuse them:
- Functional (FR) – what the system does. Example: "User can reset password via email."
- Non-functional (NFR) – system behavior characteristics. Example: "The login page must respond within 200ms under 500 concurrent users."
- Constraints – external conditions that cannot be changed. For instance: "Integration only with Russian payment gateways" or "deployment to a closed network without internet access."
The best format for functional requirements is User Story + Acceptance Criteria + technical details. This approach halves the time needed for writing tests compared to traditional tables and improves requirement understanding by 30%.
How SRS Saves Budget
A detailed SRS reduces rework costs by up to 40%. One client saved 1.2 million rubles by ordering an SRS before development began. Another project avoided rework worth 800 thousand rubles. According to our project statistics, having a complete specification reduces the number of bugs during development by 25% and cuts regression testing time by 30%. This is a direct path to a predictable budget and timeline. Find out how much your project could save – contact us.
Example: Functional Requirement FR-047
## FR-047: Two-Factor Authentication (TOTP)
**As a** registered user,
**I want** to enable 2FA via an authenticator app,
**So that** my account is protected from unauthorized access.
### Acceptance Criteria
**Enabling 2FA:**
- AC-047-1: When navigating to security settings, the "Two-Factor Authentication" section is displayed.
- AC-047-2: When clicking "Enable," the system generates a TOTP secret (RFC 6238, SHA-1, 6 digits, 30 sec.).
- AC-047-3: The QR code for Google Authenticator / Authy renders correctly.
- AC-047-4: After entering the first valid code, 2FA is activated.
- AC-047-5: The system provides 10 one-time backup codes (8 characters, a-z0-9).
**Login with 2FA:**
- AC-047-6: After entering a valid password, a code input form appears.
- AC-047-7: The code is accepted with a tolerance of ±1 time window (90 seconds back or forward).
- AC-047-8: Invalid code returns an error, attempt counter increments (+1), limit 5 attempts.
- AC-047-9: A backup code is accepted as 2FA and is invalidated after use.
**Disabling:**
- AC-047-10: To disable 2FA, the current password plus a valid 2FA code are required.
### Technical Details
**API:**
POST /api/auth/2fa/setup → { secret, qr_url, backup_codes } POST /api/auth/2fa/verify Body: { code } → { enabled: true } POST /api/auth/2fa/disable Body: { password, code } POST /api/auth/2fa/challenge Body: { code | backup_code } → { token }
**Storage:**
- `totp_secret` is encrypted with AES-256-GCM before saving in the database.
- The encryption key is from KMS, not stored in code.
- `backup_codes` are bcrypt hashes, not plaintext.
**Database Migration:**
```sql
ALTER TABLE users
ADD COLUMN totp_secret_enc TEXT,
ADD COLUMN totp_enabled BOOLEAN NOT NULL DEFAULT FALSE,
ADD COLUMN totp_verified_at TIMESTAMPTZ;
CREATE TABLE totp_backup_codes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
code_hash TEXT NOT NULL,
used_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Related Requirements: FR-001 (Registration), FR-002 (Login), NFR-SEC-003
Dependencies: Library otplib or equivalent supporting RFC 6238
</details>
## Non-Functional Requirements: How to Make Them Measurable
Non-measurable NFRs are useless: "the system must be fast" cannot be verified. All NFRs must have a concrete metric, measurement condition, and data source.
| Metric | Target Value | Measurement Condition |
|--------|--------------|------------------------|
| P50 latency | < 50ms | Load 100 rps, 4 CPU cores |
| P95 latency | < 200ms | Same |
| P99 latency | < 500ms | Same |
| Error rate | < 0.1% | Load 100 rps, 10 minutes |
| Throughput | ≥ 200 rps | Until P95 degrades > 500ms |
**Verification Tool:** k6 (scenario in `tests/load/api-baseline.js`)
**Check Frequency:** Before every release on staging
Another example – availability: uptime ≥99.5% per month (downtime ≤3.65 h), planned windows – 30 minutes between 02:00–04:00 MSK with 48h notice. RTO ≤30 min, RPO ≤1 hour. Verification – UptimeRobot every minute from 3 regions. We use a security checklist when describing NFRs.
## Why Requirements Traceability Is Not a Luxury
An SRS is valuable when you can trace any piece of code to "this implements FR-047." Requirements traceability speeds up bug finding by 3 times compared to scattered documentation. It is achieved through:
1. Naming tests after requirement identifiers:
```typescript
describe('FR-047: TOTP 2FA', () => {
it('AC-047-7: accepts code with ±1 window tolerance', async () => {
// ...
});
it('AC-047-8: locks after 5 failed attempts', async () => {
// ...
});
});
- Comments on key decisions in code:
// NFR-SEC-001: rotate refresh token on each use
async function refreshAccessToken(refreshToken: string) {
const session = await validateAndInvalidateRefreshToken(refreshToken);
const newRefreshToken = await createRefreshToken(session.userId);
const accessToken = createAccessToken(session.userId);
return { accessToken, refreshToken: newRefreshToken };
}
Linking requirements to code reduces bug search time and simplifies reviews. In our experience, this cuts regression testing time by 25%.
How to Distinguish a Good Specification from a Bad One
A good SRS undergoes review by three groups: the client checks business rules, developers check feasibility, and QA check verifiability. Typical problems of a poor specification:
| Issue | Example | Solution |
|---|---|---|
| Ambiguity | "upload several files" – how many? What size? | Specify limits: max 10 files, up to 5 MB each |
| Contradictions | In one place sorting by date, in another by popularity | Conduct a review round and consolidate a single rule |
| Missing scenarios | Happy path described but not errors | Add alternative scenarios: server failure, invalid input |
We guarantee that every item in our SRS is verifiable and implementable.
What Our SRS Creation Service Includes
- An SRS document in Markdown or Confluence with a complete description of functional and non-functional requirements.
- A numbered traceability matrix.
- A requirements dependency graph.
- A review of the document involving developers and testers.
- Consultations for requirement clarification at all stages.
Our certified engineers have extensive experience in web development and have delivered over 50 SRS documents for projects of varying complexity. Over time, we have accumulated a base of ready-made templates and solutions that speeds up SRS creation by 20%.
Comparison of Requirements Documentation Approaches
| Approach | Writing Speed | Client Understandability | Developer Completeness |
|---|---|---|---|
| User Story + AC | Medium | High | High |
| Use Case | High | Medium | Medium |
| Traditional TЗ | High | Low | Low |
Timeline and Cost
The timeline for writing an SRS for an application with 40–60 functional requirements is three to four weeks. It includes business process analysis, structured interviews, writing, two review rounds, and final approval. Cost is calculated individually – contact us for a project assessment. Get a free expert consultation.







