| name | guidewire-rate-limits |
| description | Manage Guidewire Cloud API rate limits, quotas, and throttling.
Use when encountering 429 errors, optimizing API call patterns,
or implementing rate limit handling strategies.
Trigger with phrases like "guidewire rate limit", "api quota",
"429 error", "throttling", "api limits guidewire".
|
| allowed-tools | Read, Write, Edit, Bash(curl:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Guidewire Rate Limits
Overview
Understand and manage Guidewire Cloud API rate limits, implement proper throttling, and optimize API usage patterns.
Prerequisites
- Understanding of HTTP rate limiting concepts
- Access to Guidewire Cloud Console for quota monitoring
- Familiarity with exponential backoff patterns
Rate Limit Structure
Default Limits (Guidewire Cloud)
| Limit Type | Default Value | Scope |
|---|
| Requests per second | 50 | Per tenant |
| Requests per minute | 1,000 | Per tenant |
| Requests per hour | 30,000 | Per tenant |
| Concurrent requests | 25 | Per application |
| Payload size | 10 MB | Per request |
| Query result limit | 1,000 | Per request |
Rate Limit Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1706312400
X-RateLimit-Scope: tenant
Retry-After: 60
Instructions
Step 1: Monitor Rate Limit Headers
interface RateLimitInfo {
limit: number;
remaining: number;
resetTime: Date;
scope: string;
}
class RateLimitTracker {
private current: RateLimitInfo | null = null;
updateFromResponse(response: AxiosResponse): void {
const headers = response.headers;
this.current = {
limit: parseInt(headers['x-ratelimit-limit'] || '1000'),
remaining: parseInt(headers['x-ratelimit-remaining'] || '1000'),
resetTime: new Date(parseInt(headers['x-ratelimit-reset'] || '0') * 1000),
scope: headers['x-ratelimit-scope'] || 'tenant'
};
if (this.current.remaining < this.current. * ) {
.();
}
}
(): {
(!.) ;
.. > || () > ..;
}
(): {
(!. || .. > ) ;
.(, ...() - .());
}
}
Step 2: Implement Exponential Backoff
interface BackoffConfig {
initialDelayMs: number;
maxDelayMs: number;
multiplier: number;
jitterFactor: number;
}
class ExponentialBackoff {
private attempt: number = 0;
private config: BackoffConfig;
constructor(config: Partial<BackoffConfig> = {}) {
this.config = {
initialDelayMs: config.initialDelayMs || 1000,
maxDelayMs: config.maxDelayMs || 60000,
multiplier: config.multiplier || 2,
jitterFactor: config.jitterFactor || 0.1
};
}
getNextDelay(): number {
const baseDelay = Math.min(
this.config.initialDelayMs * Math.pow(this.config., .),
..
);
jitter = baseDelay * .. * (.() * - );
.++;
.(baseDelay + jitter);
}
(): {
. = ;
}
}
makeRequestWithBackoff<T>(
: <T>,
: =
): <T> {
backoff = ();
( attempt = ; attempt < maxRetries; attempt++) {
{
result = ();
backoff.();
result;
} (error) {
(error.?. === ) {
retryAfter = (error..[] || ) * ;
delay = .(retryAfter, backoff.());
.();
(delay);
;
}
error;
}
}
();
}
Step 3: Implement Request Queue
import PQueue from 'p-queue';
class RateLimitedClient {
private queue: PQueue;
private rateLimiter: RateLimitTracker;
constructor(requestsPerSecond: number = 40) {
this.queue = new PQueue({
concurrency: 10,
interval: 1000,
intervalCap: requestsPerSecond
});
this.rateLimiter = new RateLimitTracker();
}
async request<T>(config: AxiosRequestConfig): Promise<T> {
return this.queue.add(async () => {
const waitTime = this.rateLimiter.getWaitTime();
if (waitTime > 0) {
console.log(`Waiting ${waitTime}ms due to rate limit`);
(waitTime);
}
response = axios.<T>(config);
..(response);
response.;
});
}
batchRequest<T, R>(
: T[],
: <R>,
: { ?: ; ?: } = {}
): <R[]> {
{ batchSize = , delayBetweenBatches = } = options;
: R[] = [];
( i = ; i < items.; i += batchSize) {
batch = items.(i, i + batchSize);
batchResults = .(batch.( .((item))));
results.(...batchResults);
(i + batchSize < items.) {
(delayBetweenBatches);
}
}
results;
}
}
Step 4: Optimize API Patterns
async function getAccountWithPoliciesBad(accountId: string): Promise<any> {
const account = await client.get(`/account/v1/accounts/${accountId}`);
const policies = await client.get(`/account/v1/accounts/${accountId}/policies`);
const contacts = await client.get(`/account/v1/accounts/${accountId}/contacts`);
return { account, policies, contacts };
}
async function getAccountWithPoliciesGood(accountId: string): Promise<any> {
return client.get(`/account/v1/accounts/${accountId}?include=policies,contacts`);
}
async function getActivePoliciesBad(accountId: string): Promise<Policy[]> {
response = client.();
response..( p.. === );
}
(): <[]> {
response = client.(
);
response.;
}
(): <[]> {
: [] = [];
: | ;
{
response = client.(
,
{ : { : , cursor } }
);
policies.(...response.);
cursor = response.?.;
} (cursor);
policies;
}
Step 5: Implement Circuit Breaker
enum CircuitState {
CLOSED = 'CLOSED',
OPEN = 'OPEN',
HALF_OPEN = 'HALF_OPEN'
}
class CircuitBreaker {
private state: CircuitState = CircuitState.CLOSED;
private failures: number = 0;
private lastFailureTime: Date | null = null;
private successCount: number = 0;
constructor(
private failureThreshold: number = 5,
private resetTimeoutMs: number = 60000,
private halfOpenSuccessThreshold: number = 3
) {}
async execute<T>(operation: () => Promise<T>): Promise<T> {
if (this.state === CircuitState.OPEN) {
(.()) {
. = .;
. = ;
} {
();
}
}
{
result = ();
.();
result;
} (error) {
.(error);
error;
}
}
(): {
. = ;
(. === .) {
.++;
(. >= .) {
. = .;
.();
}
}
}
(: ): {
(error.?. === ) {
.++;
. = ();
(. >= .) {
. = .;
.();
}
}
}
(): {
(!.) ;
.() - ..() >= .;
}
}
Gosu Rate Limit Handling
// Gosu implementation of rate limit handling
package gw.integration.ratelimit
uses gw.api.util.Logger
uses java.util.concurrent.Semaphore
uses java.util.concurrent.TimeUnit
class RateLimiter {
private static final var LOG = Logger.forCategory("RateLimiter")
private var _permits : Semaphore
private var _lastRefill : long
private var _refillInterval : long
private var _maxPermits : int
construct(maxRequestsPerSecond : int) {
_maxPermits = maxRequestsPerSecond
_permits = new Semaphore(maxRequestsPerSecond)
_lastRefill = System.currentTimeMillis()
_refillInterval = 1000
}
function acquire() : boolean {
refillPermits()
return _permits.tryAcquire(5, TimeUnit.SECONDS)
}
private function refillPermits() {
var now = System.currentTimeMillis()
var elapsed = now - _lastRefill
if (elapsed >= _refillInterval) {
var periods = (elapsed / _refillInterval) as int
var permitsToAdd = Math.min(periods * _maxPermits, _maxPermits - _permits.availablePermits())
_permits.release(permitsToAdd)
_lastRefill = now
}
}
function executeWithRateLimit<T>(operation() : T) : T {
if (!acquire()) {
LOG.warn("Rate limit exceeded, request blocked")
throw new RateLimitException("Rate limit exceeded")
}
try {
return operation()
} finally {
// Permit is consumed, will be refilled later
}
}
}
Monitoring Rate Limits
interface RateLimitMetrics {
totalRequests: number;
rateLimitedRequests: number;
avgResponseTime: number;
currentUsage: number;
limit: number;
}
class RateLimitMonitor {
private metrics: RateLimitMetrics = {
totalRequests: 0,
rateLimitedRequests: 0,
avgResponseTime: 0,
currentUsage: 0,
limit: 1000
};
recordRequest(duration: number, rateLimited: boolean): void {
this.metrics.totalRequests++;
if (rateLimited) {
this.metrics.rateLimitedRequests++;
}
this.metrics.avgResponseTime =
(this.metrics.avgResponseTime * (this.metrics.totalRequests - 1) + duration) /
..;
}
(: , : ): {
.. = limit - remaining;
.. = limit;
}
(): {
{ .... };
}
(): {
.();
}
}
Output
- Rate limit tracking and monitoring
- Exponential backoff implementation
- Request queue with throttling
- Circuit breaker protection
Error Handling
| Error | Cause | Solution |
|---|
429 Too Many Requests | Exceeded rate limit | Implement backoff, check headers |
503 Service Unavailable | Temporary overload | Retry with backoff |
| Circuit breaker open | Repeated failures | Wait for reset timeout |
| Queue timeout | Backpressure | Increase queue capacity |
Resources
Next Steps
For security implementation, see guidewire-security-basics.