Skip to content

Incremental Service Requirements Best Practices

This document provides guidance on writing high-quality incremental service requirements for modifying or extending existing Arda backend services. Follow these practices when creating or reviewing an Incremental Service Requirements document.

When to Use Incremental vs. New Service Requirements

Section titled “When to Use Incremental vs. New Service Requirements”
ScenarioDocument Type
Creating a new service/module from scratchService Implementation Requirements
Adding new methods to existing serviceIncremental Service Requirements
Modifying behavior of existing methodsIncremental Service Requirements
Adding properties to existing entitiesIncremental Service Requirements
Adding new child entities to existing parentsIncremental Service Requirements
Schema migrationsIncremental Service Requirements
Bug fixes affecting documented behaviorIncremental Service Requirements

Focus on what is changing, not rewriting the entire service specification. The incremental document should:

  • Reference existing documentation (not duplicate it)
  • Clearly mark changes as NEW, MODIFY, or REMOVE
  • Describe current behavior before proposing new behavior

Always document the current state before the proposed change. Reviewers need context to evaluate:

  • Whether the change is necessary
  • Whether the change is backward compatible
  • What the migration path looks like

Required pattern:

### Current Behavior
<What the system does now>
### Proposed Behavior
<What the system will do after the change>
### Change Reason
<Why this change is needed>

Every change should be evaluated for backward compatibility.

CategoryDescriptionAction Required
Fully CompatibleNo client changes neededDeploy freely
AdditiveNew optional featuresUpdate clients optionally
DeprecatingOld behavior still works but discouragedPlan migration window
BreakingOld behavior stops workingCoordinate with all consumers

When changes are not fully backward compatible, document:

  • How existing data will be migrated
  • How existing clients should update
  • Rollback procedures if deployment fails

Link every proposed change back to:

  • The original specification it modifies
  • The source code location being changed
  • The business requirement driving the change

Best Practices:

  1. New properties should be nullable or have defaults.
  2. Document how existing records will be handled.
  3. Consider serialization compatibility for API responses.

Backward Compatibility Checklist:

  • Property is nullable or has a default value
  • Existing records work without the new field
  • API clients receiving responses handle missing/new field
  • API clients sending requests work without the new field

Avoid changing types. Prefer adding a new property and deprecating the old one.

ModificationSafe Approach
Widen type (e.g., IntLong)Usually safe, verify no overflow
Narrow type (e.g., StringEnum)Requires data validation/migration
Add enum valueSafe if clients use when with else
Remove enum valueBreaking — map to replacement value
Make required → optionalSafe for new code
Make optional → requiredBreaking — backfill required

New validation rules should not reject previously valid data. If stricter validation is needed, add it with a migration period and document whether validation applies retroactively or only to new writes.

Avoid if possible. Signature changes often break API contracts.

If a signature change is required:

Change TypeSafe Approach
Add optional parameterProvide default value
Add required parameterCreate new method, deprecate old
Change return typeCreate new method, deprecate old
Remove parameterMay be safe, verify no callers depend on it

Required Documentation:

  1. Current behavior for each qualifier (LAX/STRICT/PROPAGATE)
  2. Proposed behavior clearly marked as change
  3. Reason for change
  4. Impact on existing callers

Behavioral Change Risk Assessment:

Risk LevelDescriptionMitigation
LowMore permissive (accepts more inputs)Usually safe
MediumAdditional side effectsDocument, notify consumers
HighMore restrictive (rejects previously valid inputs)Feature flag, migration period
CriticalDifferent successful outcomesRequires explicit version bump

Safe Migration Sequence:

-- Step 1: Add nullable column
ALTER TABLE item ADD COLUMN new_field VARCHAR(255);
-- Step 2: Backfill existing data
UPDATE item SET new_field = COALESCE(old_field, 'default') WHERE new_field IS NULL;
-- Step 3: Add NOT NULL constraint (after confirming backfill)
ALTER TABLE item ALTER COLUMN new_field SET NOT NULL;

Avoid in production migrations:

  • DROP COLUMN (data loss)
  • ALTER COLUMN TYPE requiring a table rewrite
  • Adding NOT NULL without default on large tables
  • Index creation without CONCURRENTLY
  • Current state documented: Existing behavior is clearly described
  • Changes marked clearly: NEW / MODIFY / REMOVE annotations used
  • Reason documented: Why each change is needed
  • References linked: Original specs, source files, requirements linked
  • API compatibility assessed: Impact on REST endpoints documented
  • Data compatibility assessed: Impact on existing records documented
  • Client impact documented
  • Serialization safe: New fields are nullable or have defaults
  • Schema migration defined: SQL scripts with rollback
  • Data migration defined: How existing data is transformed
  • Deployment order specified
  • Rollback plan defined
  • Existing tests identified: Which tests need updates
  • New tests specified: Test cases for new/modified behavior
  • Regression tests planned

Changing method behavior without documenting the impact on existing callers.

Fix: Always include current behavior, new behavior, who is affected, and migration path.

Bundling multiple unrelated changes into one requirements document.

Fix: Create separate documents for distinct features, independent bug fixes, and unrelated schema changes. This makes rollback easier and review more focused.

Only documenting the forward path.

Fix: Every schema migration and behavioral change should have rollback SQL, service rollback procedure, and data recovery steps.

Rewriting the entire service specification when only changing one method.

Fix: Reference the original spec and document only the delta.

Not explicitly analyzing backward compatibility because “it’s just adding a field.”

Fix: Complete the compatibility checklist even for simple changes. “Simple” changes often have subtle impacts:

  • Nullable field with null default → API response now includes null
  • New validation → Previously valid inputs now rejected
  • New enum value → when expressions may not be exhaustive

Use requirement IDs in:

  • Commit messages: feat(item): implement EM-ISU-001 - add category field
  • PR descriptions: Reference each requirement being implemented
  • Test names: MM-ISU-001 - update with category propagates to children

After changes are deployed:

  1. Update the original service specification to reflect new state.
  2. Archive or mark the incremental document as “implemented.”
  3. Update API documentation.