Self-hosted platform for standing up and running software factories on AWS: complete DevSecOps environments with secure delivery pipelines, supply-chain controls, compliance evidence and multi-tenant governance — in minutes, not months.
Price-only adjustments an operator grants on top of an account’s subscription: a temporary reduction (one-time or recurring) or a standing balance, both realized as a usage credit that offsets future costs.
v1.<base64url>, fresh every time). A guessed or hand-crafted string is rejected.This is the reference for operator-granted discounts: the code format, the mint → issue → redeem lifecycle, per-provider handling, promotions and referrals, and the admin and self-service API.
Written for operators minting discounts and for admins redeeming them. Two things it is not about: the caps and tiers themselves (see feature tiers and add-on bundles), and the automatic composition-based credits earned from add-on combos — those share the same credit machinery but are not operator-granted.
value:unit:kind string. Ceilings apply.billing:manage pastes the token on their own billing page.recurring rule tops the credit up every period until it is removed.A subscription may hold one standing recurring rule at a time; credits themselves accumulate freely.
BILLING_DISCOUNTS_ENABLED is on by default; set false to 404 the routes and hide the surface.BILLING_DISCOUNT_KEYS holds versioned AES-256-GCM keys (v1:<base64-32B>,v2:…); the highest version mints and older keys still decode, so they can be rotated.BILLING_METERING_ENABLED on. Validate first with BILLING_METERING_DRAWDOWN_DRYRUN=true, which logs the intended withholding but reports full quantities and leaves the balance untouched.BILLING_PROMOTIONS_ENABLED has the same opt-out default, and additionally requires BILLING_DISCOUNTS_ENABLED — discounts off means promotions off.| Variable | Default | Description |
|---|---|---|
BILLING_DISCOUNTS_ENABLED |
true |
Master switch — set false to 404 the discount routes |
BILLING_DISCOUNT_KEYS |
— | Secret. Versioned AES-256-GCM keys v1:<base64-32B>,v2:… |
BILLING_DISCOUNT_MAX_PERCENT |
100 |
Ceiling on a percent discount |
BILLING_DISCOUNT_MAX_CENTS |
10000000 |
Ceiling on a dollar/credit discount, in cents |
BILLING_PROMOTIONS_ENABLED |
true |
Auto-granting promotions; requires discounts enabled |
BILLING_METERING_ENABLED |
off | Required for Marketplace credit realization |
BILLING_METERING_DRAWDOWN_DRYRUN |
false |
Log intended withholding without changing anything |
BILLING_PROMOTION_BACKFILL_INTERVAL_MS |
— | Backfill cron cadence (leader-locked) |
BILLING_PROMOTION_CLAWBACK_WINDOW_MS |
7 days | Cancel-within window that reverses a promo grant |
See Environment Variables → Billing.
Every discount is authored in a compact, human-readable form and issued — when handed to a customer — as an opaque, unforgeable token.
What an operator types when minting:
value : unit : kind [ : campaign ]
| Field | Values | Notes |
|---|---|---|
value |
positive integer | percent points, or whole dollars (stored as cents) |
unit |
dollar | percent |
aliases $ / % |
kind |
onetime | recurring | credit |
see the kinds |
campaign |
optional label | e.g. summer24, for reporting |
Examples: 50:percent:onetime · 25:dollar:recurring · 100:dollar:credit · 50:percent:onetime:summer24
A customer never sees the authoring form. Mode-B issuance seals the discount into an opaque AES-256-GCM token (v1.<base64url>), non-deterministic — a fresh token every time — and unforgeable: only a holder of the signing key can mint one that decodes, so a guessed or hand-crafted string is rejected.
A discount is never forwarded to the provider as a coupon object. Every kind resolves to a usage credit that billing owns, banked as a balance and applied against future costs. The only difference between the kinds is how much and how often the credit is granted:
| Kind | Grant | Realized as |
|---|---|---|
onetime |
a one-time credit = the reduction (percent-of-plan or dollars), granted once | a usage credit consumed by the next invoice |
recurring |
the reduction re-granted every period (a standing rule) until removed | a usage credit topped up each cycle |
credit |
a one-time credit of the value, drawn down over time | a usage-credit balance |
The credit is realized on the customer’s balance at the provider — Stripe posts a negative customer-balance transaction, applied to upcoming invoices. There is no coupon and no per-subscription discount object.
A percent discount is resolved to dollars from the plan price at grant time, so a recurring percent discount tracks plan changes: each period’s credit is recomputed from the then-current price.
Combo discounts are a second, automatic source of usage credits: holding a qualifying set of add-ons (for example the Analytics Suite or Team Growth Bundle) grants a recurring credit for the bundled saving, using the same balance mechanism. They are composition-based rather than operator-granted — see Combo pricing.
How a discount reaches an account depends on the billing provider. The in-app discount surface described here is Stripe-only; AWS Marketplace plan-level discounts are handled on the AWS side.
POST /billing/admin/discounts with value:unit:kind./apply, a direct grant to { targetOrgId }) or Mode B (/token, hand the customer an opaque token or public alias).billing:manage).recurring rule re-grants each period.Nothing is sent to Stripe as a coupon.
Marketplace has no customer-balance primitive, so in-app credits are realized by withholding reported metered usage.
When both BILLING_DISCOUNTS_ENABLED and BILLING_METERING_ENABLED are on, the provider reports usageCreditSupport: 'metered' and the same mint → redeem flow applies to Marketplace accounts; a banked credit is drawn down on the metering cycle.
When metering is off, the provider reports usageCreditSupport: 'none' and the routes reject these accounts (DISCOUNTS_UNSUPPORTED, HTTP 409). A credit is never accepted unless the mechanism that realizes it is running — no banking without realization.
Per metering cycle (gated, default-off):
YYYY annual / YYYY-MM monthly), the standing recurring discount plus any active combo credits are re-granted onto the local balance. Marketplace has no invoices to drive Stripe’s reconciler, so the cycle drives it.units − withheld to BatchMeterUsage, where the withheld units’ value (at the dimension’s configured price, AWS_MARKETPLACE_DIMENSION_PRICE_MAP, cents per unit per cycle) is drawn from the balance. Whole units only; the remainder carries forward.unprocessed === 0), emitting credit_consumed and credit_exhausted at zero. Multi-pod safe via atomic conditional updates.Known limitation. Withholding offsets metered add-on usage only — never the base plan contract line. So a recurring plan-percent discount on an account with little or no metered add-on usage realizes only partially, or not at all. The un-drawable surplus is surfaced via a warn plus the billing_marketplace_credit_unrealizable_total metric rather than silently lost.
For plan-level or contract pricing, use an AWS Marketplace private offer:
ResolveCustomer).The discount lives entirely in AWS, so no in-app discount record is created and it does not surface as a discount/credit line in the billing dashboard, which reads the local ledger rather than AWS pricing.
Generation (mint the record) and issuance (deliver it) are separate steps, both system-admin only.
| Mode | How | Best for |
|---|---|---|
| A — direct grant | The operator applies the discount straight onto a target account’s subscription. The customer never sees a token; the discount simply appears on their bill. | Sales and support grants |
| B — distributed token | The operator issues an opaque token, or a short public alias like SUMMER50, and delivers it out of band (email, landing page). The customer redeems it themselves. |
Promos |
Redemption happens two ways:
billing:manage pastes a token or alias on their own billing page. They can only ever discount their own account.A discount bound to a targetOrgId is redeemable only by that account. An untargeted (public) discount is redeemable by anyone, subject to maxRedemptions, redeemBy and tier restrictions.
Because a token only seals the discount id, one discount can back many tokens — re-issuing mints a fresh string against the same record and shared redemption counter.
Revoking (isActive: false) invalidates every token for that discount at once, since redemption always validates the live record rather than the string. Revoking does not strip a discount already applied to a subscription — remove those explicitly.
A promotion is the marketing counterpart to a discount. Where a discount is redeemed (a code someone enters) or manually granted, a promotion auto-grants a usage credit when an org hits a trigger, bounded by a campaign budget.
It is a grant source, reusing the same usage-credit machinery (creditBalanceCents / creditLedger, drawn down on the invoice or by Marketplace metered withholding), so there is no new realization path.
A promotion fires on a lifecycle event evaluated against the org’s subscription:
| Trigger | For |
|---|---|
subscription_created |
Signup / first-subscription campaigns (with firstSubscriptionOnly) |
plan_change |
Upgrade / conversion campaigns |
manual |
Admin-only; granted via POST /admin/promotions/:id/grant |
referral |
Two-sided — see Referrals |
Eligibility (trigger.conditions, all must match): tiers, intervals, firstSubscriptionOnly. Plus an active window (startsAt / endsAt).
Each grant atomically reserves from budgetCents (a guarded $inc), then applies the credit idempotently per (promotion, org) via a creditLedger.dedupeKey. Any failure after reservation compensates ($inc -cents) — so concurrent triggers can never overspend, and the bias is always under-spend.
spentCents / grantsCount are a reconciled advisory cache; the ledger (Σ promo:<id> entries) is the source of truth. GET /admin/promotions/:id/spend returns both and their drift.
A promotion never grants when the provider can’t realize a usage credit (usageCreditSupport === 'none') — it warns instead of banking an unrealizable credit. perOrgCapCents clamps a single grant; maxGrants caps total grants.
unit: 'dollar' (cents) or 'percent' (percent of the current plan price, resolved at grant time).
kind: 'onetime' grants once. kind: 'recurring' re-grants each billing period from the periodic reconcile/metering path with period-keyed idempotency, so a redelivered invoice never double-grants. It stops when the promo is revoked, out of window, over budget, or the org is no longer eligible.
POST /admin/promotions/:id/activate grants across the existing eligible base now — idempotent per org, budget-bounded, with skips logged rather than silent.
A backfill cron (BILLING_PROMOTION_BACKFILL_INTERVAL_MS, leader-locked) periodically does the same for every active promo, so a grant dropped by a transient failure, or a campaign activated after an org’s signup, still lands.
A grant is reversed — ledger row pulled, balance reduced, budget released, promotion_clawback emitted — if the subscription cancels within the clawback window (BILLING_PROMOTION_CLAWBACK_WINDOW_MS, default 7 days). This defuses signup-grab-churn.
Revoking a promotion (isActive: false, or DELETE) stops future auto-grants; credits granted earlier and outside the clawback window stay.
A referral promotion is two-sided. A new org subscribes with a referral code — the referrer’s org id — via referralCode on POST /billing/subscriptions:
value), and a pending Referral is recorded.referrerValue (or the same as the referee if unset). Gating on first payment defeats fake-referral farming.Guards: no self-referral; a referee is referred at most once (unique); the referrer must be a real subscribed org; and both grants flow through the shared budget and idempotency machinery — referee keyed per org, referrer keyed per pair. A referral whose referrer grant can’t be funded still marks qualified, so it won’t retry forever.
All routes are under /billing and gated by BILLING_DISCOUNTS_ENABLED.
| Method | Path | Gate | Purpose |
|---|---|---|---|
POST |
/admin/discounts |
system admin | Mint a discount (ceiling-checked) |
POST |
/admin/discounts/:id/token |
system admin | Mode B — issue / re-issue an opaque token |
POST |
/admin/discounts/:id/apply |
system admin | Mode A — direct grant to { targetOrgId } |
GET |
/admin/discounts · /:id |
system admin | List (filter by campaign/active/target) / inspect |
PUT · DELETE |
/admin/discounts/:id |
system admin | Edit / revoke |
POST |
/subscriptions/:id/discounts |
billing:manage |
Self-service redeem a token or alias |
DELETE |
/subscriptions/:id/discounts/:discountId |
billing:manage |
Stop a standing recurring discount (granted credits persist) |
GET |
/events |
billing:read |
The caller’s own billing events — credit applied/consumed/exhausted, discounts, combos (own org only) |
Every mutation writes a local billing_events row and mirrors to the central audit trail: billing.discount.generate / .issue / .apply / .remove / .revoke, plus billing.credit.consumed / .exhausted and billing.combo.expired for usage-credit realization, attributing both the acting party and the affected account.
Tokens, signing keys and aliases are never logged or audited — only the discount id, kind and value. An account can review its own credit movement via GET /billing/events (billing:read).
BILLING_DISCOUNT_MAX_PERCENT / BILLING_DISCOUNT_MAX_CENTS cap the magnitude an operator can mint.maxRedemptions before mutating the subscription, so concurrent redemptions can’t exceed the cap; a failed apply compensates the reservation.BILLING_DISCOUNT_KEYS as a sealed secret.BILLING_METERING_ENABLED is on, with credits realized by withholding metered usage, priced via AWS_MARKETPLACE_DIMENSION_PRICE_MAP. Default-off, so enable and validate with BILLING_METERING_DRAWDOWN_DRYRUN first. Withholding offsets metered add-on usage only — for plan-level or contract pricing use private offers.GET /billing/summary). This is where an account sees the effect of its discounts.