Writing Web Application Requirements Specification
A Software Requirements Specification (SRS) differs from Technical Specification (TS) by audience and depth: TS is a contract with the customer at the "what the system does" level, while SRS is a tool for developers and testers at the "how exactly the system does it" level. Real-world projects often combine these documents, but understanding the difference in detail is crucial.
Classification of Requirements
Requirements are divided into three categories, and it's important not to confuse them:
Functional (FR) — what the system can do. "A user can reset their password via email."
Non-functional (NFR) — characteristics of system behavior. "The login page must respond in 200ms with 500 concurrent users."
Constraints — external conditions that cannot be changed. "Integration only with Russian payment gateways," "GDPR compliance," "deployment in an isolated environment without internet access."
Format for Describing Functional Requirements
The best format for developers is User Story + Acceptance Criteria + technical details:
## FR-047: Two-Factor Authentication (TOTP)
**As** a registered user,
**I want** to enable 2FA through an authenticator app,
**So that** I can protect my account 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: QR code for Google Authenticator / Authy is displayed correctly
- AC-047-4: After entering the first correct code, 2FA activates
- AC-047-5: System issues 10 one-time backup codes (8 characters, a-z0-9)
**Login with 2FA:**
- AC-047-6: After entering the correct password, a code entry form appears
- AC-047-7: Code is accepted with ±1 time window tolerance (90 sec. ago or forward)
- AC-047-8: Incorrect code — error, attempt counter (+1), limit of 5 attempts
- AC-047-9: Backup code is accepted as 2FA, invalidated after use
**Disabling:**
- AC-047-10: Disabling 2FA requires current password + valid 2FA code
### 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 to database
- Encryption key — from KMS, not stored in code
- `backup_codes` — 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: otplib library or equivalent supporting RFC 6238
### Non-Functional Requirements: Making Them Measurable
Unmeasurable NFRs are useless: "the system should be fast" — impossible to verify. All NFRs must have specific metrics, measurement conditions, and data sources.
```markdown
## NFR-PERF-001: API Performance
| 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 > 500ms degradation |
**Verification Tool:** k6 (scenario in `tests/load/api-baseline.js`)
**Check Frequency:** Before each release to staging
## NFR-AVAIL-001: Availability
- Uptime ≥ 99.5% per month (≤ 3.65 hours downtime)
- Planned downtime: up to 30 minutes, at 02:00–04:00 UTC, with 48 hours notice
- RTO (Recovery Time Objective): ≤ 30 minutes
- RPO (Recovery Point Objective): ≤ 1 hour
**Measurement:** UptimeRobot (HTTP check every minute, 3 regions)
## NFR-SEC-001: Session Management
- JWT access token TTL: 15 minutes
- Refresh token TTL: 30 days, rotation on each use
- Maximum active sessions per user: 5
- On compromise: invalidate all user tokens in O(1)
**Verification:** Manual testing by OWASP Session Management checklist
Managing Dependencies Between Requirements
In real projects, requirements depend on each other. A dependency graph helps understand development order:
FR-001 (Registration)
└→ FR-002 (Login)
└→ FR-047 (2FA)
└→ FR-048 (2FA Backup Codes)
└→ FR-003 (Password Recovery)
└→ FR-010 (Email Verification)
FR-020 (Product Catalog)
└→ FR-021 (Shopping Cart)
└→ FR-022 (Checkout)
└→ INT-001 (Payment ЮKassa)
└→ INT-002 (Shipping SDEK)
Requirements Traceability
SRS is valuable when for any piece of code you can say: "this implements FR-047." This is achieved through:
- Naming tests by requirement identifiers:
describe('FR-047: TOTP 2FA', () => {
it('AC-047-7: accepts code with ±1 window tolerance', async () => {
// ...
});
it('AC-047-8: blocks after 5 incorrect attempts', async () => {
// ...
});
});
- Comments on key decisions in code:
// NFR-SEC-001: refresh token rotation 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 };
}
Specification Review
The specification must be reviewed by three groups:
- Customer / Product Owner: are business rules correct?
- Developers: is it technically feasible, are there contradictions?
- QA: can this be tested, are there enough details?
Typical issues revealed by review:
- Ambiguity: "user can upload multiple files" — how many maximum? What size?
- Contradictions: in one place "sorting by default — by date," in another — "by popularity"
- Missing scenarios: happy path described, errors not described
Timeline
SRS for an application with 40–60 functional requirements — three to four weeks. Includes: analysis of business processes, conducting structured interviews, writing, two rounds of review, final approval. The document is not static — when requirements change, the version is updated via PR.







