Enforcement Patterns

Three patterns for enforcing entitlement limits: hard block, soft overage, and grace period.

The Enforcement Decision

When a customer exceeds a limit entitlement, ABAXUS tells you via the exceeded: true flag in the check response. What happens next is your decision — ABAXUS provides the data; your product enforces the policy. This flexibility lets you choose the right business behavior for each feature and customer segment.

There are three standard patterns, each with different tradeoffs.


Pattern 1: Hard Block

Behavior: Immediately reject requests that would exceed the limit. Return a 429 Too Many Requests error with a clear message explaining why and how to upgrade.

When to use: For limits that enforce a genuine product constraint (not just a pricing tier) — API rate limits to prevent abuse, storage quotas tied to infrastructure costs, features that are technically unavailable on lower tiers.

Implementation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
async function handleApiRequest(customerId, req) {
  const entitlement = await checkEntitlement(customerId, 'api_calls_per_month');

  if (entitlement.exceeded) {
    return Response.json({
      error: 'rate_limit_exceeded',
      message: 'You have exceeded your monthly API call limit.',
      limit: entitlement.limit,
      current_usage: entitlement.current_usage,
      upgrade_url: 'https://app.yourproduct.com/settings/billing/upgrade'
    }, { status: 429 });
  }

  // Proceed with the request
  return processRequest(req);
}

The check call should happen before the expensive part of your request processing to fail fast. Cache the check result in the request context to avoid redundant calls within the same request lifecycle.


Pattern 2: Soft Overage

Behavior: Allow usage beyond the defined limit but charge for it at the overage rate. The customer is never blocked, but usage beyond the limit results in additional line items on their invoice.

When to use: For limits that are primarily pricing tiers rather than hard constraints — API calls where the cost to you scales with usage, storage where you can provision more capacity, any case where blocking would be more harmful to the relationship than billing for overages.

Implementation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
async function handleApiRequest(customerId, req) {
  const entitlement = await checkEntitlement(customerId, 'api_calls_per_month');

  // Always proceed — log the overage for billing purposes
  if (entitlement.exceeded) {
    // Optionally: notify the customer they're in overage
    logger.info('customer_in_overage', {
      customer_id: customerId,
      feature: 'api_calls_per_month',
      overage: Math.abs(entitlement.remaining)
    });
  }

  return processRequest(req);
}

The overage usage flows into ABAXUS as normal events. At billing time, if your price plan has a tiered charge for api_calls with an upper tier that covers overage usage, the billing engine automatically calculates the overage charge from the raw events. No special invoice handling is needed — the pricing model handles it.

This is why tiered pricing and soft overage enforcement work together naturally: the tiered pricing definition in the plan IS the overage pricing, implicitly.


Pattern 3: Grace Period

Behavior: When a limit is first exceeded, start a grace period (typically 1–7 days) during which the customer continues to have access. If they upgrade before the grace period expires, they’re retroactively within their limit. If they don’t upgrade, switch to a hard block.

When to use: For subscription-critical features where an abrupt block would cause significant disruption — core API access, data export features, features that affect their own customers. Gives the customer time to notice and react.

Implementation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
async function handleApiRequest(customerId, req) {
  const entitlement = await checkEntitlement(customerId, 'api_calls_per_month');

  if (!entitlement.exceeded) {
    return processRequest(req);
  }

  // Check grace period state in your own database
  const grace = await getGracePeriod(customerId, 'api_calls_per_month');

  if (!grace) {
    // First exceedance — start the grace period
    await startGracePeriod(customerId, 'api_calls_per_month', { days: 3 });
    await notifyCustomerLimitExceeded(customerId);
    return processRequest(req);  // Allow during grace
  }

  if (grace.isActive()) {
    // In grace period — allow but remind
    return processRequest(req);
  }

  // Grace period expired — hard block
  return Response.json({
    error: 'limit_exceeded',
    message: 'Your grace period has ended. Please upgrade to continue.',
    upgrade_url: '...'
  }, { status: 429 });
}

The grace period state is managed in your own application database, not in ABAXUS. ABAXUS provides the real-time limit check; your application layer handles the grace window business logic.


Choosing the Right Pattern

PatternBest forRisk
Hard blockRate limits, abuse prevention, hard resource constraintsAbrupt UX — can cause churn if limits are hit unexpectedly
Soft overageUsage-proportional costs, good customer relationshipsSurprise invoice amounts if customers aren’t warned about overage rates
Grace periodBusiness-critical features, enterprise customersComplexity in your application layer, potential for gaming

You can apply different patterns to different features within the same product. API rate limits might use hard block, while storage quotas use soft overage, and premium features use a grace period.


Mapping Soft Overage to Billing

For soft overage to produce correct invoices, your price plan must have a charge that covers the overage usage range. If the limit is 100,000 API calls/month and you use soft overage enforcement, your tiered pricing should extend beyond 100,000:

1
2
3
4
5
6
7
8
{
  "metric_key": "api_calls",
  "pricing_model": "tiered",
  "tiers": [
    { "up_to": 100000, "unit_price": 0 },
    { "up_to": null, "unit_price": 0.0002 }
  ]
}

Usage above 100k is priced at $0.0002/call. The entitlement limit says “100k included”; the pricing model says “anything above that costs extra.” They work in concert: the entitlement drives your enforcement decision; the pricing model drives the invoice calculation.