The promotions module stores discount and custom-price rules in the database. Base prices remain in your application's plan definitions in src/lib/payments/plans.ts; promotion rules are applied to those prices during checkout.
Promotion management is available to administrators at /admin/promotions. Customer-facing pages only resolve a code and display or apply the resulting price.
Product keys
Promotion rules use namespaced product keys so identifiers from different billing areas do not collide:
Use a key such as app:your-plan-id for an application plan, or app:* to match all plans in that namespace.
An exact key takes precedence over a namespace wildcard when both rules exist. Namespaces are application-defined and can be added without a schema change.
Pricing modes
percentstores a percentage from 0 to 100.fixed_discountstores a discount in the currency's minor units.fixed_pricestores the resulting price in minor units.
The checkout flow calculates the final amount server-side from the canonical base price. It passes the custom amount to the active payment adapter and disables provider-side promotion entry for that checkout. Promotion codes are normalized server-side before they are applied.
Feature flag
ENABLE_PROMOTIONS="false"
When disabled, the admin page and navigation item are hidden, /admin/promotions returns 404, and application checkout ignores promotion codes.