Usage based limits

Usage-based limits let you control feature access based on a merchant's activity, consumption, or other measurable metrics. This approach enables flexible pricing models where merchants are limited based on their usage patterns or allocated resources.

How usage-based limits work

Usage-based limits in Mantle combine two key components:

  1. Usage events - Track specific actions or consumption in your app
  2. Limit features - Define maximum thresholds in Mantle's feature system

When a merchant's usage approaches or exceeds their plan's limits, you can control access to features and prompt upgrades as needed.

Implementation steps

1. Configure usage metrics

Before implementing usage-based limits, set up appropriate usage metrics in Mantle:

  • Create metrics that aggregate the events you want to limit
  • Configure the appropriate time period (month-to-date or billing period)
  • Link these metrics to features in your plans

2. Track usage events

When merchants use limited features, send usage events to Mantle:

// Using MantleClient
await mantleClient.sendUsageEvent({
  eventName: 'product_created',
  properties: {
    productId: '123',
    productType: 'physical'
  }
});

// Or direct API request
await fetch('https://appapi.heymantle.com/v1/usage_events', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Mantle-App-Id': process.env.MANTLE_APP_ID,
    'X-Mantle-Customer-Api-Token': customerApiToken
  },
  body: JSON.stringify({
    eventName: 'product_created',
    properties: {
      productId: '123',
      productType: 'physical'
    }
  })
});

3. Check limits before access

Before allowing a merchant to use a limited feature, check their current usage against their plan limit:

async function canCreateProduct() {
  // Get limit from merchant's current plan
  const limit = await mantleClient.limitForFeature({
    featureKey: 'product_limit'
  });
  
  // Get current usage
  const { customer } = await mantleClient.getCustomer();
  const used = customer.usage['Product limit']?.currentValue || 0;
  
  // Check if merchant is within limit
  return used < limit;
}

4. Enforce limits in your application

Implement the limit check in the appropriate place in your code flow:

async function createProduct(productData) {
  // Check feature limit before proceeding
  const limit = await mantleClient.limitForFeature({
    featureKey: 'product_limit'
  });
  const { customer } = await mantleClient.getCustomer();
  const used = customer.usage['Product limit']?.currentValue || 0;
  
  if (used >= limit) {
    throw new Error('Product limit reached');
  }
  
  // Proceed with product creation
  const product = await actuallyCreateProduct(productData);
  
  // Track usage after successful creation
  await mantleClient.sendUsageEvent({
    eventName: 'product_created',
    properties: {
      productId: product.id,
      productType: product.type
    }
  });
  
  return product;
}

5. Display remaining capacity to merchants

Keep merchants informed about their usage and limits:

import { useMantle } from '@heymantle/react';

function ProductLimitIndicator() {
  const { customer, limitForFeature } = useMantle();
  
  const productLimit = limitForFeature({
    featureKey: 'product_limit'
  });
  
  const used = customer.usage['Product limit']?.currentValue || 0;
  const remaining = productLimit - used;
  const usagePercentage = (used / productLimit) * 100;
  
  return (
    <div>
      <ProgressBar percentage={usagePercentage} />
      <Text>
        {used} of {productLimit} products used ({remaining} remaining)
      </Text>
      {remaining <= 5 && (
        <Banner status="warning">
          You're approaching your product limit. Consider upgrading your plan.
        </Banner>
      )}
    </div>
  );
}

Common usage-based limit patterns

Pre-check pattern

Check limits before performing actions:

// Check limit before allowing feature access
if (await canUseFeature('product_limit')) {
  // Allow feature access
} else {
  // Show upgrade prompt
}

Track-then-check pattern

Track usage and then verify against limits for reporting:

// Track usage first
await trackUsage('api_call');

// Then check if user is approaching limit for notifications
if (await isApproachingLimit('api_calls')) {
  // Show warning about upcoming limit
}

Batch-check pattern

For bulk operations, check if the entire batch can be processed:

const batchSize = products.length;
const remainingCapacity = await getRemainingCapacity('product_limit');

if (batchSize > remainingCapacity) {
  // Can't process entire batch, show error or process partial
} else {
  // Process entire batch
}

Best practices

  1. Check limits early in your request lifecycle to prevent wasted processing
  2. Track usage accurately even when limits are exceeded for reporting purposes
  3. Provide clear feedback when merchants reach their limits
  4. Offer upgrade paths when limits are approached or reached
  5. Consider grace periods for small overages to improve user experience
  6. Cache limit values when appropriate to reduce API calls

Did this page help you?