Writing an SDD
An SDD is a one-page design you write before coding an architecture-led task (see Ways of Working).
It exists to make decisions visible and approved — not to describe code.
Seed it from deploy/templates/SDD.md.
Small bug / one rule? Skip it — that’s TDD.
Anatomy — what each section must answer
| Section | Answers | Keep it to |
|---|---|---|
Goal |
the one outcome, why now |
1–2 sentences |
Scope |
in / out (the "out" prevents creep) |
bullets |
Affected components |
which modules/packages (from |
a short list |
Design + alternatives |
the chosen approach and the options you rejected (+ why) |
a paragraph + 2 bullets |
Data & DB |
DTOs/records, tables/columns ( |
only what changes |
FE↔BE contract |
envelope / error codes / verb+path / identity — or "none" |
the delta only |
Protocol |
TR-069/181/369 / LwM2M paths validated vs spec — or "N/A" |
the paths touched |
Logging & metrics |
|
1–3 lines |
Test plan |
unit |
bullets |
Risks / rollout |
migration/back-compat risk, what’s deferred |
bullets |
Do / don’t
| ✅ Do | ❌ Don’t |
|---|---|
|
|
Live example — a complete, approved SDD
# SDD: Bulk-disable CPEs by serial — ft-device-network-service
Status: APPROVED (2026-06-26, CTO) · Task grade: architecture-led · Ticket: OPS-412
## 1. Problem & goal
During an incident, ops must disable many CPEs fast. Today it's one-by-one in the UI. Goal: one call
that disables a list of serials and reports which were unknown.
## 2. Scope
- In: REST endpoint + service + the disable path through CpeWriteService.
- Out: UI, scheduling/automation, re-enable (separate ticket).
## 3. Affected components
- network.cpe.rest.CpeController (new action) · network.cpe.service.CpeWriteService (reuse)
- new request record in network.cpe.rest (role sub-package)
## 4. Design / approach
Add a northbound REST action `PUT api/Cpe/disable` taking a serial list; fan out through the existing
CpeWriteService batch path. Chosen over: (a) per-serial loop in the controller — rejected, N round-trips;
(b) a new async job — rejected, ops needs a synchronous result now.
## 5. Data & DB
No schema change. Audit cols already present. Batch the write at the J-DB relational tier (~1000).
## 6. FE↔BE contract
External REST (StatusResponse). No internal UI↔BE change.
## 7. Protocol
N/A (no parameter-path changes).
## 8. Logging & metrics
log per device: deviceId=<serial> action=disable result=...; counter cpe.disable.count.
## 9. Test plan
- should_disable_all_when_serials_valid (*IT, emulator)
- should_report_unknown_serials_when_some_missing (*IT)
- should_cap_when_list_exceeds_batch_limit (*Test)
## 10. Risks / rollout
Large lists → cap at 1000 with a clear 4xx. No migration; safe to ship behind the existing ops role.
Template → deploy/templates/SDD.md. Back to Ways of Working · Overview.
|