Rate Limits
FieldMCP uses a per-org rate limit model. Each connected John Deere organization adds its own quota. Connect more orgs, get more capacity.
Limits
| Limit | Per org | 5 orgs | 10 orgs |
|---|---|---|---|
| Monthly requests | 17,000 | 85,000 | 170,000 |
| Per-minute requests | 100 | 500 | 1,000 |
Limits scale linearly with connected organizations. There is no per-developer aggregate cap beyond the sum of your connected orgs.
What Counts as a Request
Each MCP tool call to the gateway counts as one request. This includes all tools: listing fields, getting boundaries, running diagnostics, fetching weather.
Requests that don't count: failed requests due to rate limiting (HTTP 429) and validation errors (MISSING_REQUIRED_PARAM, INVALID_PARAM_VALUE, etc.) are not counted against your quota.
For pricing details, see Pricing.
What You'll See at the Limit
When your per-minute or monthly limit is exceeded, the gateway returns:
- HTTP 429 status code
- A JSON error body with
rateLimitsmetadata
{
"error": "Rate limit exceeded. Try again in 12 seconds.",
"errorCode": 429,
"rateLimits": {
"minuteRemaining": 0,
"minuteResetAt": 1712345678000,
"monthlyRemaining": 4200,
"monthlyResetAt": 1714521600000
}
}The X-RateLimit-Remaining Header
Every successful response includes an X-RateLimit-Remaining header showing how many per-minute requests you have left. Use this to throttle proactively instead of waiting for a 429.
HTTP/1.1 200 OK
X-RateLimit-Remaining: 87
X-Request-Id: req-abc123
When X-RateLimit-Remaining drops below 10, slow down. When it hits 0, the next request will return 429.
Recovery
Use exponential backoff when you hit a 429:
async function callWithBackoff(fn: () => Promise<Response>, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fn();
if (response.status !== 429) return response;
const body = await response.json();
const resetAt = body.rateLimits?.minuteResetAt;
const waitMs = resetAt
? Math.max(0, resetAt - Date.now()) + Math.random() * 1000
: (2 ** attempt) * 1000 + Math.random() * 1000;
await new Promise(resolve => setTimeout(resolve, waitMs));
}
throw new Error('Rate limit exceeded after retries');
}Proactive throttling is better than reactive backoff. Monitor X-RateLimit-Remaining and space your requests to stay under the limit:
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') ?? '100');
if (remaining < 10) {
await new Promise(resolve => setTimeout(resolve, 2000)); // slow down
}Scaling
Need more capacity? Connect more farm organizations. Each org adds 17,000 monthly requests and 100 requests per minute.
| Orgs | Monthly cost | Monthly requests | Per-minute |
|---|---|---|---|
| 1 | $29 | 17,000 | 100 |
| 5 | $145 | 85,000 | 500 |
| 10 | $261 (10% volume discount) | 170,000 | 1,000 |
| 25 | $652.50 | 425,000 | 2,500 |
For enterprise-scale needs beyond 25 orgs, contact sales.
Provider Rate Limits
John Deere has its own API rate limits, separate from FieldMCP's. When the gateway hits a Deere rate limit, it retries automatically with exponential backoff before surfacing the error to your MCP client.
If the gateway exhausts its retries, you'll see a RATE_LIMIT_PROVIDER error code in the MCP tool response (not an HTTP 429). This means Deere itself is throttling. Wait the retryAfter seconds and try again.
See Error Handling for the full error code reference.