Skip to content
getnextpdf.com

Enterprise edition

Billing

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.

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.

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.

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.

Terminal window
composer require nextpdf/enterprise:^3

The 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.

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.25
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);
}
  • Budget-alert never blocks. Under a budget-alert policy checkQuota does 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.

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.

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.

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.

  • 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.

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.

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.

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.

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.

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.

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.