429 Too Many Requests on bulk user updates via Kotlin SDK — backoff strategy?

We’re hitting a wall with the Genesys Cloud Kotlin SDK (genesys-cloud-auth) when trying to bulk update user profiles. We have about 500 users to sync every morning. The current implementation uses a simple loop with async/await to call UsersApi.updateUser() for each record. It works fine for the first 50-100 requests, then starts throwing HttpClientException: HTTP 429 Too Many Requests.

The error response body is pretty standard:

{
 "code": "tooManyRequests",
 "message": "Rate limit exceeded. Please retry after 10 seconds."
}

I’ve tried adding a static delay(10000) after every 50 requests, but that feels brittle. Sometimes the rate limit kicks in at request 42, sometimes at 98. The Retry-After header isn’t always present in the 429 response from the /api/v2/users/{userId} endpoint, which makes implementing a standard exponential backoff tricky.

Here’s the core of the update function:

suspend fun syncUser(userId: String, profile: UserProfile) {
 try {
 val request = UpdateUserRequest(profile)
 usersApi.updateUser(userId, request)
 } catch (e: HttpClientException) {
 if (e.statusCode == 429) {
 // Current hack: wait 10s
 delay(10000)
 syncUser(userId, profile) // Recursive retry
 } else {
 throw e
 }
 }
}

This recursive approach is causing stack overflow risks if the rate limit persists. Is there a recommended pattern for handling bulk updates in Kotlin? Should I be using a coroutine channel with a semaphore to limit concurrency, or is there a specific batch endpoint I’m missing that avoids the per-user rate limit? The UsersApi doesn’t seem to have a bulkUpdate method like the OrganizationsApi does. We’re running this from an Android background worker, so network conditions can vary too. Any code examples for a proper retry handler with exponential backoff that respects the Retry-After header when it exists would be huge.