How OpenSEO Manages Batch Processing and Keyword Limits for Rank Tracking
OpenSEO processes rank-tracking requests in fixed batches of 10 keywords, enforces strict limits of 1,000 keywords per configuration and 20 configurations per project, and applies device-specific multipliers to calculate accurate API costs before submitting requests to DataForSEO.
The open-source repository every-app/open-seo implements a defensive architecture for rank tracking that prevents API quota exhaustion through hard-coded batch processing and keyword limits. These constraints are defined in src/shared/rank-tracking.ts and enforced across the scheduler, UI validation, and cost estimation modules. Understanding these limits reveals how the platform maintains predictable performance while scaling to thousands of tracked keywords.
Batch Processing Architecture
Fixed Batch Sizes of 10 Keywords
The core batching mechanism relies on the KEYWORDS_PER_BATCH constant set to 10 in src/shared/rank-tracking.ts (line 30). When the system executes a rank check, it divides the total keyword set into chunks of exactly 10 keywords, regardless of the total volume. This fixed size ensures that each API call to DataForSEO remains within optimal payload limits while allowing the background worker to process keywords incrementally.
The batching logic appears in the cost estimation and scheduling layers. For example, when validating a bulk keyword upload, the code splits arrays using this constant:
import { KEYWORDS_PER_BATCH, MAX_KEYWORDS_PER_CONFIG } from "@/shared/rank-tracking";
// Example: validating a bulk keyword upload
function validateUpload(keywords: string[]) {
if (keywords.length > MAX_KEYWORDS_PER_CONFIG) {
throw new Error(
`You can only track up to ${MAX_KEYWORDS_PER_CONFIG} keywords per config.`,
);
}
// Split into batches for API calls
const batches = [];
for (let i = 0; i < keywords.length; i += KEYWORDS_PER_BATCH) {
batches.push(keywords.slice(i, i + KEYWORDS_PER_BATCH));
}
return batches; // each batch will be sent to DataForSEO
}
Scheduling and Timing Constraints
Each batch is allocated 6 seconds of processing time, defined by SECONDS_PER_BATCH = 6 at line 33 of src/shared/rank-tracking.ts. This value drives the scheduler's rate-limiting logic, allowing the system to estimate queue depth and prevent job overlap. By multiplying the number of batches by this constant, OpenSEO predicts total execution time and communicates expected completion windows to users.
Keyword and Configuration Limits
Per-Configuration Keyword Caps
OpenSEO enforces a hard limit of 1,000 keywords per rank-tracking configuration via MAX_KEYWORDS_PER_CONFIG = 1000 (line 36). A configuration represents a unique domain and location combination. The UI applies this constraint during manual entry and bulk import operations, rejecting uploads that exceed the threshold. This limit prevents individual configurations from monopolizing background worker threads and ensures fair resource distribution across projects.
Project-Level Configuration Constraints
At the project level, the system caps configurations at 20 per project using MAX_CONFIGS_PER_PROJECT = 20 (line 39). Since each configuration can track up to 1,000 keywords, this effectively allows 20,000 keywords per project. This constraint protects the scheduler from being overwhelmed by projects with excessive location or domain variants, maintaining predictable latency for all users.
Cost-Aware Batching Logic
Device Multipliers and SERP Requests
Before batching occurs, OpenSEO calculates the total SERP request volume by multiplying keyword count against device settings. The devicesCount helper function (lines 28-31 in src/shared/rank-tracking.ts) converts the device setting—desktop, mobile, or both—into a numeric multiplier of 1 or 2. When a user selects "both," each keyword generates two distinct SERP requests, doubling the batch count required.
The total request count follows the formula: keywordCount × devicesCount(devices). These requests are then grouped into batches of 10 for actual API transmission.
Credit Estimation with estimateRankCheckCredits
The estimateRankCheckCredits function (lines 62-73) applies the cost model to inform users of expected expenses before execution. It accepts the keyword count, device setting, search depth, and API priority level, then returns both credit and USD estimates:
import { estimateRankCheckCredits } from "@/shared/rank-tracking";
async function showCostPreview(
keywordCount: number,
devices: "desktop" | "mobile" | "both",
depth: number,
) {
const { costUsd, costCredits } = estimateRankCheckCredits(
keywordCount,
devices,
depth,
"queued", // scheduled runs use the cheaper queued API
);
console.log(`Estimated cost: $${costUsd.toFixed(2)} (${costCredits} credits)`);
}
This estimation relies on the same batch sizing logic used during actual execution, ensuring that previewed costs match actual billing.
Validation and Data Flow
The batch processing and keyword limits propagate through multiple system layers. The schema definitions in src/types/schemas/rank-tracking.ts enforce structural validation, while the server-side retrieval logic in src/server/features/rank-tracking/services/rankTrackingResults.ts assumes batched data structures when aggregating SERP results. Client-side hooks like src/client/features/rank-tracking/useRankRunPolling.ts and src/client/features/rank-tracking/useRankCheckTrigger.ts respect the 6-second batch timing when polling for updates or triggering manual checks.
Summary
- Batch sizing: OpenSEO processes exactly 10 keywords per batch (
KEYWORDS_PER_BATCH), as defined insrc/shared/rank-tracking.ts. - Timing: Each batch consumes approximately 6 seconds (
SECONDS_PER_BATCH), driving scheduler estimates. - Keyword limits: Single configurations max out at 1,000 keywords (
MAX_KEYWORDS_PER_CONFIG). - Configuration limits: Projects are capped at 20 configurations (
MAX_CONFIGS_PER_PROJECT). - Cost calculation: The
devicesCountmultiplier andestimateRankCheckCreditsfunction calculate total SERP requests and credits before API calls. - API protection: These constraints collectively prevent DataForSEO API overload and maintain predictable queue performance.
Frequently Asked Questions
What is the maximum number of keywords allowed per rank-tracking configuration in OpenSEO?
OpenSEO limits each rank-tracking configuration to 1,000 keywords via the MAX_KEYWORDS_PER_CONFIG constant in src/shared/rank-tracking.ts (line 36). This constraint applies to both manual keyword entry and bulk CSV imports, with validation occurring at the UI and API layers to prevent oversized configurations from degrading system performance.
How does OpenSEO calculate the cost of a rank check before execution?
The platform uses the estimateRankCheckCredits function to multiply the keyword count by the device multiplier (1 for single device, 2 for both desktop and mobile), then applies the batch cost model. This calculation occurs in src/shared/rank-tracking.ts and provides users with accurate credit and USD estimates before they commit to the API request.
Why does OpenSEO restrict projects to 20 rank-tracking configurations?
The MAX_CONFIGS_PER_PROJECT = 20 limit (line 39) prevents the background scheduler from being overwhelmed by projects that track hundreds of domain or location combinations. By capping configurations, the system ensures that batch processing queues remain predictable and that API rate limits are distributed fairly across all projects in the instance.
How long does OpenSEO allocate for processing each keyword batch?
Each batch of 10 keywords is allocated 6 seconds of processing time based on the SECONDS_PER_BATCH constant (line 33). This timing estimate drives the job scheduler's rate-limiting logic and determines how the UI calculates expected completion times for large rank-tracking runs.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →