How the DataForSEO API Client Handles Billing Metering and Lazy Loading in Open SEO

The DataForSEO API client in Open SEO uses dynamic imports to lazy-load the heavy SDK on first request, while wrapping every fetch method with a meter helper that checks usage credits before execution and records exact costs afterward.

The Open SEO repository implements a sophisticated integration with the DataForSEO API that solves two critical operational challenges: keeping the server bundle size minimal and ensuring accurate usage-based billing. This article examines how the DataForSEO API client manages billing metering and lazy loading through a combination of dynamic imports and credit-tracking wrappers.

Lazy Loading Architecture

The client keeps the approximately 3 MB DataForSEO SDK out of the eager startup graph by isolating all heavy SDK code in a separate lazy chunk. When you create a client instance using createDataforseoClient(), the methods themselves are lightweight proxies that do not immediately import the SDK.

Instead, each method calls loadDataforseoSections(), which performs a dynamic import of the section barrel at src/server/lib/dataforseo/sections.ts. This ensures the large DataForSEO SDK loads only when a method is first invoked, significantly improving cold-start performance. The lazy-loading boundary is explicitly documented in src/server/lib/dataforseo/client.ts with a comment explaining that the sections are loaded on demand via import("@/server/lib/dataforseo/sections").

Billing Metering Flow

Every public fetch method is wrapped by the meter helper, which implements a consistent billing pattern across all DataForSEO operations. The meter function receives the customer context, a picker that selects the concrete fetcher from the lazy-loaded sections, and an optional default credit feature.

The wrapper returns a function that executes the following sequence:

  1. Credit Feature Resolution – Determines the credit feature using input.creditFeature ?? defaultFeature. The mapping from API paths to credit features is defined in src/shared/billing-credit-features.ts.
  2. Pre-flight Validation – Checks the organization's usage-credit balance before executing the request.
  3. Execution and Tracking – Runs the DataForSEO request and records the exact provider-reported cost via trackUsageCreditSpend.

Hosted Mode Credit Checks

When running in hosted mode (isHostedServerAuthMode() returns true), the meterDataforseoCall function implements full billing integration:

  • Customer Resolution – Calls getOrCreateOrganizationCustomer to resolve the Autumn customer associated with the organization.
  • Balance Validation – Uses assertUsageCreditsAvailable to verify sufficient credits exist before proceeding.
  • Cost Tracking – After successful execution, trackDataforseoCost records the exact billing.costUsd and updates the credit balance.
  • Error Handling – Even errors that already incurred a charge (such as DataforseoChargedTaskError) are tracked via trackDataforseoCost before re-throwing the exception.

This logic appears in src/server/lib/dataforseo/client.ts between lines 37 and 88, ensuring every hosted request either charges the organization accurately or fails fast if credits are insufficient.

Non-Hosted Mode Bypass

In self-hosted deployments where isHostedServerAuthMode() returns false, the wrapper skips all credit checks and billing logic entirely. The meter simply returns the raw result from the underlying DataForSEO fetcher without interacting with Autumn or the credit system. This design matches the specification outlined in specs/0002-hosted-dataforseo-metering-with-autumn.md, which defines the responsibilities and bypass conditions for non-hosted environments.

Implementation Details

The client architecture separates concerns across three distinct layers:

Client CreationcreateDataforseoClient(customer) receives a BillingCustomerContext and returns an object with methods like serp.live and keywords.related. Each method is constructed using the meter helper, binding the specific DataForSEO endpoint to the billing wrapper.

Credit Feature Mapping – The system uses strongly-typed credit features defined in src/shared/billing-credit-features.ts to categorize spend by API endpoint. This enables granular analytics and cost attribution across different types of SEO data (SERP results, keyword research, etc.).

Meter Wrapper – The meter function abstracts the complexity of async loading and billing verification. It handles the dynamic import of sections, the conditional billing logic based on server mode, and the translation of DataForSEO responses into usage credit records.

Usage Examples

Creating a Client and Executing a Metered Request

import { createDataforseoClient } from "@/server/lib/dataforseo";

// billingCustomer is a BillingCustomerContext obtained from the request
const dataforseo = createDataforseoClient(billingCustomer);

// Fetch live SERP results with automatic billing metering
const serpResults = await dataforseo.serp.live({
  target: "google.com",
  location_code: 2840, // United States
});

This call triggers loadDataforseoSections() to dynamically import the SDK, then executes the billing flow before returning results.

Overriding Credit Features for Specific Requests

const result = await dataforseo.keywords.related({
  keyword: "open seo",
  // Attribute spend to a custom feature instead of the default "keyword_research"
  creditFeature: "ai_citations",
});

The meter wrapper reads input.creditFeature and uses this value when recording the usage credit spend, allowing flexible cost attribution across different product features.

Direct Execution in Non-Hosted Mode

// In self-hosted deployments without Autumn integration
const rawResult = await dataforseo.labs.keywordOverview({
  target: "open seo",
});

When isHostedServerAuthMode() is false, the wrapper bypasses assertUsageCreditsAvailable and trackDataforseoCost, returning the raw provider data without billing side effects.

Summary

  • Lazy Loading – The DataForSEO SDK (~3 MB) loads only on first use via loadDataforseoSections(), which dynamically imports src/server/lib/dataforseo/sections.ts.
  • Billing Wrapper – Every method uses the meter helper to enforce consistent credit checking and cost tracking across all API calls.
  • Hosted Mode – Validates credits via assertUsageCreditsAvailable, resolves Autumn customers with getOrCreateOrganizationCustomer, and records exact costs using trackDataforseoCost.
  • Non-Hosted Mode – Skips billing logic entirely when isHostedServerAuthMode() is false, executing requests directly.
  • Credit Features – Maps API endpoints to billing categories defined in src/shared/billing-credit-features.ts for granular spend tracking.

Frequently Asked Questions

How does the client prevent the DataForSEO SDK from bloating the server startup?

The client uses dynamic imports via loadDataforseoSections() to defer loading of src/server/lib/dataforseo/sections.ts until the first API method is called. This keeps the heavy SDK out of the initial server bundle, reducing cold-start times and memory footprint until SEO data is actually requested.

What happens if an organization runs out of credits during a request?

The meterDataforseoCall function calls assertUsageCreditsAvailable before executing any DataForSEO request. If insufficient credits exist, the function throws an error immediately, preventing the API call from executing and consuming provider resources that couldn't be billed.

How does the system handle partial failures or errors that still incur costs?

The billing wrapper catches DataforseoChargedTaskError and other error conditions that indicate the provider already processed the request. Before re-throwing the error, it calls trackDataforseoCost to record the incurred cost against the organization's credit balance, ensuring accurate billing even for failed operations.

Can I use the DataForSEO client without the Autumn billing system?

Yes. When isHostedServerAuthMode() returns false (typical in self-hosted deployments), the meter wrapper skips all credit checks and directly returns the raw DataForSEO result. This allows the client to function as a thin proxy over the provider API without requiring Autumn integration or credit management.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →