Skip to content

SystemSubscriptionDiscountManager

Manages admin-granted subscription discounts with lifecycle tracking, separate from reusable promo codes.

Purpose

SystemSubscriptionDiscountManager handles one-off discounts that admins grant to specific subscriptions. Unlike promo codes (which are reusable codes users enter), system discounts are applied directly to a subscription by an admin with a reason, and tracked independently with their own lifecycle.

Each subscription can have at most one active discount at a time. Discounts track how many billing cycles they have been applied to, and can be configured with a maxCycles limit after which they automatically transition to "exhausted" status. Admins can also manually cancel discounts with a reason for audit purposes.

The manager supports bulk lookup for the renewal flow, allowing efficient retrieval of active discounts across multiple subscriptions in a single query.

Error Codes (SystemDiscountError)

ErrorCondition
INVALID_USER_IDEmpty or missing user ID
INVALID_SUBSCRIPTION_IDEmpty or missing subscription ID
INVALID_DISCOUNT_TYPENot "percentage" or "dollar_off"
INVALID_DISCOUNT_VALUENon-positive, NaN, infinite, or percentage > 1
INVALID_MAX_CYCLESLess than 1 or not an integer
INVALID_REASONEmpty or missing reason
INVALID_GRANTED_BYEmpty or missing admin identifier
SUBSCRIPTION_ALREADY_HAS_ACTIVE_DISCOUNTSubscription already has an active discount
DISCOUNT_NOT_FOUNDDiscount ID does not exist
DISCOUNT_ALREADY_CANCELLEDAttempting to cancel/increment an already cancelled discount
DISCOUNT_ALREADY_EXHAUSTEDAttempting to cancel/increment an exhausted discount
CANCEL_RACE_CONDITIONConcurrent cancel: discount was already modified
INCREMENT_RACE_CONDITIONConcurrent increment: discount was already modified

State & Storage

In-Memory State

None. This is a stateless manager.

SQLite Tables

admin_subscription_discounts

ColumnTypePurpose
idINTEGER PKAuto-increment ID
user_idTEXTTarget user ID
subscription_idTEXTTarget subscription ID
discount_typeTEXT"percentage" or "dollar_off"
discount_valueTEXTDiscount amount
max_cyclesINTEGER NULLMax billing cycles; NULL for unlimited
cycles_appliedINTEGERNumber of billing cycles discount has been applied (default 0)
statusTEXT"active", "cancelled", or "exhausted"
reasonTEXTAdmin-provided reason for granting
granted_byTEXTAdmin identifier who granted
granted_atINTEGERUnix timestamp of grant
cancelled_byTEXT NULLAdmin who cancelled
cancelled_atINTEGER NULLUnix timestamp of cancellation
cancel_reasonTEXT NULLReason for cancellation
last_applied_atINTEGER NULLTimestamp of last cycle increment

Interactions

Depends On

  • BaseDurableManager (base class)
  • SQLite storage via this.durable.state.storage.sql

Depended By

  • PromoCodeRegistry DO -- exposes all methods as RPC endpoints (grantSystemDiscount, cancelSystemDiscount, etc.)
  • Admin endpoints -- grant, cancel, list operations
  • Subscription renewal flow -- getBulkActiveDiscounts and incrementCyclesApplied during billing

Edge Cases & Error Handling

  • One active discount per subscription enforced by checking for existing active discount before granting
  • Race conditions on cancel and increment handled via WHERE status = 'active' guard with rowsWritten check
  • incrementCyclesApplied is NOT idempotent -- caller must deduplicate per billing cycle
  • Percentage discount values must be <= 1.0 (e.g., "0.5" for 50% off)
  • Bulk lookup returns empty map for empty input array (short-circuits)
  • Page size capped at 100 to prevent excessive query results
  • All timestamps are Unix seconds via Math.floor(Date.now() / 1000)

See Also