Enterprise edition
Billing
At a glance
Section titled “At a glance”NextPDF Enterprise tracks compute-unit (CU) usage per tenant against a plan quota and applies a configurable overage policy: block hard, block with retry guidance, or continue and alert. It also fires deduplicated usage alerts at 80%, 100%, and budget-exceeded thresholds. This page describes the observable billing behavior and the public contract.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
Billing is a base Enterprise capability with no separate per-feature flag; the plan tiers and their included quotas resolve through the plan registry.
Conceptual overview
Section titled “Conceptual overview”Billing measures consumption in compute units. Each tenant runs under a plan; each plan carries an included CU quota and a capability set. Three default plan tiers ship — Standard, Advanced, and High Control — with progressively larger included quotas and progressively broader capability sets (the higher tiers add the Intelligence and Privacy add-on packs). The registry is the canonical lookup; a white-label deployment may construct it with custom definitions.
The overage policy decides what happens when a tenant passes its included quota. A hard-stop policy blocks processing immediately and carries HTTP 402 semantics. A soft-stop policy blocks with retry guidance and carries HTTP 429. A budget-alert policy never blocks — processing continues and alerts fire instead, carrying HTTP 200. Only hard-stop and soft-stop are blocking; the quota manager raises a quota-exceeded condition only when the policy blocks and the included quota is actually exceeded.
The alert service evaluates usage against thresholds in ascending order — 80% warning, 100% warning, then budget-exceeded — and each alert type fires at most once per billing period per tenant. Budget-exceeded requires strict overage, not merely hitting 100%. Alert state is tracked through a repository interface, so deduplication survives across requests, and the service exposes a clear operation to reset alert state at billing-period rollover.
Why it works this way
Section titled “Why it works this way”Billing is built as a pure decision layer, not a storage system. Quota checks, overage math, and alert evaluation run in memory against a PlanDefinition and one current-usage figure, with no I/O on the check path. Persistence sits outside that decision: alert-dedup state is reached only through the AlertStateRepositoryInterface an operator supplies, which keeps durability and the billing-period boundary under host control. The overage outcome is a small explicit enum mapping each policy to a fixed HTTP status, so the block-or-continue decision stays deterministic and auditable. That separation lets the same billing surface run unchanged from a single instance to a metered multi-tenant fleet.
Design background: Operating NextPDF in production.
Public API surface
Section titled “Public API surface”composer require nextpdf/enterprise:^3The supported integration points are the plan registry (get, has, defaultRegistry), the quota manager (checkQuota, remainingQuota, usagePercentage), the overage calculator (calculate, returning an immutable overage result), the overage policy enum (httpStatusCode, isBlocking), and the billing alert service (evaluate, clearAlerts). The alert-state repository is an interface — supply an in-memory implementation for tests or a durable one for production.
Code sample — quick start
Section titled “Code sample — quick start”use NextPDF\Enterprise\Billing\OverageCalculator;use NextPDF\Enterprise\Billing\PlanRegistry;use NextPDF\Enterprise\Billing\SaaSPlan;
$plan = PlanRegistry::defaultRegistry()->get(SaaSPlan::Standard);$result = (new OverageCalculator())->calculate($plan, currentCu: 1_250.0);
$result->isOverage; // true — 1,250 CU against a 1,000 CU included quota$result->overageCu; // 250.0$result->usageRatio; // 1.25Code sample — production
Section titled “Code sample — production”use NextPDF\Enterprise\Billing\OveragePolicy;use NextPDF\Enterprise\Billing\QuotaExceededException;use NextPDF\Enterprise\Billing\QuotaManager;
$manager = new QuotaManager($registry, OveragePolicy::SoftStop);
try { $manager->checkQuota($tenant, SaaSPlan::Advanced, $currentCu);} catch (QuotaExceededException $e) { // SoftStop → answer with 429 + Retry-After up to the reset instant. return $this->retryAfter($e->resetsAt);}
foreach ($alertService->evaluate($tenant, $plan, $planDef, $currentCu) as $alert) { $this->notify($tenant, $alert->severity(), $alert);}Edge cases & gotchas
Section titled “Edge cases & gotchas”- Budget-alert never blocks. Under a budget-alert policy
checkQuotadoes not raise even well past quota; rely on the fired alerts, not on an exception. - Budget-exceeded needs strict overage. Hitting exactly 100% fires the 100% warning, not budget-exceeded; budget-exceeded requires usage strictly above the included quota.
- Alerts deduplicate per period. Each alert type fires once per tenant per billing period. Clear alert state at period rollover or alerts do not re-fire next period.
- Zero or unset included quota. A plan with a non-positive included quota reports a 0.0 usage ratio rather than dividing by zero.
- Period reset is the next month boundary. The default quota-exceeded reset instant is the first day of the next calendar month at midnight.
Performance
Section titled “Performance”Quota checks, overage calculation, and alert evaluation are constant-time, in-memory operations against a plan definition and the supplied current-usage figure. There is no I/O on the check path unless your alert-state repository implementation performs it.
Security notes
Section titled “Security notes”Billing decisions are derived from a tenant-scoped current-usage figure supplied by the caller; the tenant identity must come from authenticated context, never from client-supplied input. The billing surface enforces quota and emits alerts — it does not itself authenticate the tenant.
Conformance
Section titled “Conformance”Overage-policy outcomes carry standard HTTP status semantics: payment-required (402) for hard-stop, too-many-requests (429) with retry guidance for soft-stop, and success (200) for budget-alert, following the IETF HTTP semantics specification (RFC 9110) for the 402, 429, and 2xx classes.
Behavior contract
Section titled “Behavior contract”- Consumption is measured in compute units; each tenant runs under a plan with an included CU quota and a capability set.
- The overage policy is one of hard-stop (402, blocking), soft-stop (429 with retry guidance, blocking), or budget-alert (200, non-blocking); a quota-exceeded condition is raised only when the policy blocks and the included quota is actually exceeded.
- Alerts evaluate in ascending order (80% warning, 100% warning, budget-exceeded) and each type fires at most once per billing period per tenant; budget-exceeded requires strict overage.
- A non-positive included quota reports a 0.0 usage ratio rather than dividing by zero.
- Quota checks, overage calculation, and alert evaluation are constant-time in-memory operations with no I/O on the check path unless the alert-state repository performs it.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.
Core fallback
Section titled “Core fallback”NextPDF Core (Apache-2.0) has no billing, quota, or overage surface — none; this capability has no Core-tier equivalent. Core processing is not metered, quota-gated, or alerted by NextPDF.
Pro fallback
Section titled “Pro fallback”NextPDF Pro has no billing, quota, or overage surface — none; this capability has no Pro-tier equivalent. The plan registry, quota manager, overage calculator, and alert service ship in the nextpdf/enterprise package only.
Enterprise boundary note
Section titled “Enterprise boundary note”The plan registry, overage policy, and alert deduplication are described at the behavior level. The alert-state repository is an interface; durable persistence is supplied by the host, and the internal alert-state storage strategy is out of scope for the public surface.
Deployment boundary
Section titled “Deployment boundary”Billing decisions are derived from a tenant-scoped current-usage figure supplied by the caller. The operator owns the alert-state repository implementation, its persistence, and the billing-period rollover schedule. NextPDF Enterprise enforces quota and emits alerts but does not itself authenticate the tenant or persist usage.
Legal-compliance boundary
Section titled “Legal-compliance boundary”No export-control restriction applies to the billing surface. Plan inclusions, quotas, and commercial terms are governed by your license agreement, not by runtime enforcement. Consult your own advisers and your agreement for plan scope.