Ktor: What's the recommended way to implement rate-limiting?

Created on 25 Jan 2020  路  8Comments  路  Source: ktorio/ktor

For REST APIs

feature

All 8 comments

@AdityaAnand1 have you seen Resilience4j?
It has Kotlin & suspending functions support.
The code can look like:

fun Application.module(testing: Boolean = false) {
    val config = RateLimiterConfig.custom()
        .limitRefreshPeriod(Duration.ofMillis(1))
        .limitForPeriod(10)
        .timeoutDuration(Duration.ofMillis(25))
        .build()

    val rateLimiterRegistry = RateLimiterRegistry.of(config)

    val testRateLimiter = rateLimiterRegistry
        .rateLimiter("test")

    routing {
        get("/") {
            testRateLimiter.executeSuspendFunction {
                call.respondText("HELLO WORLD!", contentType = ContentType.Text.Plain)
            }
        }
    }
}

Hi @AdityaAnand1, thanks for the question. Could you tell me where you want to place the limit(on a client or on a server)?

Thanks, @viartemev I'll look into that library

@e5l On the server. Should you ever rate-limit a client? 馃

Ideally, I would want a plugin for Ktor that says:

"Hey client, you just tried to hit this API endpoint for the 100th time in 1 minute, that's not cool, here's a 429 response instead for you"

With the ability to customize the highlighted things.

It could make sense if you want to avoid such messages 馃槃

Thanks, @viartemev I'll look into that library

@e5l On the server. Should you ever rate-limit a client? thinking

Ideally, I would want a plugin for Ktor that says:

"Hey client, you just tried to hit this API endpoint for the 100th time in 1 minute, that's not cool, here's a 429 response instead for you"

With the ability to customize the highlighted things.

I made a Ktor feature for this, ktor-rate-limiting. I think it can be what you are looking for, at least to some extent (if not, perhaps you can draw inspiration from it). It is suitable for simple use cases, but perhaps not suitable for more enterprise scenarios, it will for example not work very well when you have multiple instances of the same service behind a load balancer, and it will not persist rate limits if there service is restarted.

Looks pretty good @mantono! Does it also work within the authenticate block?

Yes, it does. And you can set it to rate limit against a specific user if you have credentials available from the authentication. You'll have to change the keyExtraction value to something different then in the feature configuration block. Create an issue if something is unclear and I might be able to improve the documentation if required.

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Was this page helpful?
0 / 5 - 0 ratings