REST Lens
← Back to All Rules
Rule 83

Toggle Anti-Pattern

Category: HTTP Methods

Description

POST endpoints that toggle binary state (e.g., star/unstar, follow/unfollow, mute/unmute) should be split into separate PUT (to set) and DELETE (to unset) operations for idempotent, predictable behavior.

What It Checks

This rule analyzes POST operations in the API:

  • Only considers POST endpoints where the same path lacks both PUT and DELETE methods
  • Uses AI to determine if the operation toggles between two states
  • Flags toggle operations that should be split into explicit set/unset endpoints

Why It Matters

Splitting toggles into PUT + DELETE improves:

  • Idempotency: PUT and DELETE are idempotent by definition — clients can safely retry without unexpected state changes
  • Predictability: Callers know exactly what state they're setting, rather than hoping the toggle lands on the right side
  • Race Conditions: With a toggle, two concurrent calls cancel each other out; with PUT/DELETE, concurrent calls converge to the intended state
  • Client Simplicity: No need to first GET the current state before toggling — just PUT to set or DELETE to unset

Examples

Good

paths:
  /repos/{id}/star:
    put:
      operationId: starRepo
      summary: Star a repository
      responses:
        "204":
          description: Repository starred
    delete:
      operationId: unstarRepo
      summary: Unstar a repository
      responses:
        "204":
          description: Repository unstarred

  /users/{id}/follow:
    put:
      operationId: followUser
      summary: Follow a user
      responses:
        "204":
          description: User followed
    delete:
      operationId: unfollowUser
      summary: Unfollow a user
      responses:
        "204":
          description: User unfollowed

Bad

paths:
  /repos/{id}/star:
    post:
      operationId: toggleStar
      summary: Toggle star on a repository
      # Toggles state — not idempotent, not predictable
      responses:
        "200":
          description: Star toggled

  /users/{id}/follow:
    post:
      operationId: toggleFollow
      summary: Toggle follow status
      # Callers can't express intent — "set" vs "unset"
      responses:
        "200":
          description: Follow toggled

Exceptions

  • APIs where the toggle is intentionally atomic and the client always reads the new state from the response
  • Internal APIs with controlled concurrency where race conditions are not a concern

Configuration

This rule has no configuration options. It is either enabled or disabled.

Related Rules

  • Rule 5: GET/POST Tunneling - Detect misuse of GET/POST for other operations
  • Rule 82: Idempotent Design - POST should not be used for idempotent operations