Feature Spec Template

Use this markdown starter to align product, engineering, QA, and AI coding output. The sections below explain how to fill it in a way that survives real implementation pressure.

feature-spec-template.md
# Feature Spec Template

## Goal
- ...

## Non-goals
- ...

## Acceptance Criteria
- [ ] Given ...
- [ ] When ...
- [ ] Then ...

## Edge Cases
- null/empty:
- duplicates/idempotency:
- concurrency/race:
- permissions/visibility:

## Output / Deliverables
- API / DB / UI changes:
- Test checklist:
- Rollback notes:

When to use this template

How to fill it correctly

The Goal section should be one sentence describing the user or business outcome. Non-goals set explicit boundaries to prevent scope drift. Acceptance Criteria are binary Given/When/Then statements. The Edge Cases section covers nulls, duplicates, permission and concurrency paths. Deliverables list the exact code areas, tests, and rollback notes.

Write so a reviewer can derive test cases without asking clarifying questions.

Common mistakes

Pre-implementation review checklist

Need examples? See spec template examples and spec review checklist.

Real-world example: user notification preferences

Here is what a filled-in version of this template looks like for a real feature — letting users control which notifications they receive.

## Goal
Allow users to opt in/out of individual notification channels
(email, push, in-app) per event type, reducing unsubscribe rates
by giving granular control.

## Non-goals
- Notification delivery infrastructure changes
- Admin-level notification overrides
- Frequency capping or digest mode

## Acceptance Criteria
- [ ] Given a logged-in user on /settings/notifications
  When they toggle "Marketing emails" off and save
  Then no marketing emails are sent to that user
- [ ] Given a user with all channels disabled
  When a critical security alert fires
  Then the alert is still delivered (security is non-optional)
- [ ] Given an API consumer calling PATCH /users/:id/preferences
  When the payload omits a channel key
  Then that channel preference is unchanged (partial update)

## Edge Cases
- null/empty: user has no existing preferences → default all ON
- duplicates/idempotency: toggling the same setting twice is a no-op
- concurrency/race: two tabs saving simultaneously → last-write-wins
- permissions/visibility: users cannot modify other users' preferences

## Output / Deliverables
- API: PATCH /users/:id/notification-preferences
- DB: add notification_preferences JSONB column to users table
- UI: toggle grid component on settings page
- Test checklist: unit tests for partial update, integration test
  for security override, E2E test for toggle persistence
- Rollback: feature flag `notification_prefs_v2` → revert to
  global on/off toggle

Related resources

Editorial note

This template covers feature specification for spec-first engineering teams. The filled example is an illustrative scenario.

Tip: save it under /docs/specs/, review before implementation, and update after major requirement changes. Last updated: March 25, 2026.