{"id":18478618,"url":"https://github.com/sunny-chung/spring-starter-feign-coroutine","last_synced_at":"2026-06-23T19:31:07.217Z","repository":{"id":196073434,"uuid":"694288286","full_name":"sunny-chung/spring-starter-feign-coroutine","owner":"sunny-chung","description":"This starter module serves as a temporary solution of using Spring Boot with Coroutine Feign, until Spring Cloud OpenFeign officially supports it.","archived":false,"fork":false,"pushed_at":"2024-02-26T14:27:32.000Z","size":112,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-13T18:48:30.905Z","etag":null,"topics":["feign","http-client","kotlin-coroutines","spring-cloud"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sunny-chung.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-20T17:40:21.000Z","updated_at":"2024-08-24T12:57:21.000Z","dependencies_parsed_at":"2024-02-26T15:53:01.430Z","dependency_job_id":null,"html_url":"https://github.com/sunny-chung/spring-starter-feign-coroutine","commit_stats":null,"previous_names":["sunny-chung/spring-starter-feign-coroutine"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sunny-chung/spring-starter-feign-coroutine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunny-chung%2Fspring-starter-feign-coroutine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunny-chung%2Fspring-starter-feign-coroutine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunny-chung%2Fspring-starter-feign-coroutine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunny-chung%2Fspring-starter-feign-coroutine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sunny-chung","download_url":"https://codeload.github.com/sunny-chung/spring-starter-feign-coroutine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunny-chung%2Fspring-starter-feign-coroutine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34704742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["feign","http-client","kotlin-coroutines","spring-cloud"],"created_at":"2024-11-06T12:10:50.052Z","updated_at":"2026-06-23T19:31:07.192Z","avatar_url":"https://github.com/sunny-chung.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Feign Coroutine Starter\n\n![GitHub](https://img.shields.io/github/license/sunny-chung/spring-starter-feign-coroutine)\n![Maven Central](https://img.shields.io/maven-central/v/io.github.sunny-chung/spring-starter-feign-coroutine)\n\nNOTE: Since v0.4.0, the artifact groupId is changed to 'io.github.sunny-chung'. Also, [a dependency resolution rule is needed](#getting-started) to add to build.gradle.kts.\n\nThis starter module serves as a temporary solution of using Spring Boot with Coroutine Feign,\nuntil Spring Cloud OpenFeign officially supports it. This module provides Spring Boot integration with the\n[Feign Kotlin module](https://github.com/OpenFeign/feign/tree/master/kotlin), the reactive Spring WebClient and Micrometer.\n\nA limited set of Spring Cloud OpenFeign features is supported. *Unsupported* features include:\n- Default Encoder and Decoder beans (users must provide these beans)\n- Load balancer (URL starts with `lb://`)\n- Refresh context\n- Lazy attributes\n- AOT\n- Circuit breaker\n- PageJacksonModule and SortJacksonModule beans (users may still customize the encoders and decoders to support)\n- OAuth 2 interceptors\n- Caching\n- Client-scoped configuration beans\n- Blocking HTTP clients (users can use asynchronous HTTP clients)\n\nExcept above, users are expected to be able to migrate their existing Spring Cloud OpenFeign integrations to\nthis module directly and painlessly (hopefully).\n\n## Performance\n\nA load test was performed using JMeter against the example project in this repository.\n\nSetting:\n- 1000 concurrent threads\n- Infinite loops of calls within 200 seconds\n- Each request requires 3s non-blocking processing time\n- Call path: Spring Cloud Gateway --\u003e Example Application --(feign)--\u003e Example Application\n- All services are run inside docker containers\n- Each docker container has only 200 MB memory limit\n\n|            | Direct call without feign | **Spring Feign Coroutine Starter** | feign-kotlin          |\n|------------|---------------------------|------------------------------------|-----------------------|\n| Median     | 3025 ms                   | **3017 ms**                        | *Out-of-memory Crash* |\n| 95%        | 3149 ms                   | **3095 ms**                        | *Out-of-memory Crash* |\n| 99%        | 3322 ms                   | **3137 ms**                        | *Out-of-memory Crash* |\n| Maximum    | 3583 ms                   | **3633 ms**                        | *Out-of-memory Crash* |\n| Error      | 0.0 %                     | **0.0 %**                          | *Out-of-memory Crash* |\n| Throughput | 311.1 / s                 | **314.0 / s**                      | *Out-of-memory Crash* |\n\nIt proved that Spring Feign Coroutine Starter takes full advantages of non-blocking coroutines to achieve a performance\nsimilar to direct calling the underlying endpoint. In the test, the median latency added by this module is about 17ms.\n\nNote there is environment noise in the load test. The result does not mean using feign has lower latencies than direct call.\n\nInterested individuals may carry out tests by making use of the [JMeter script included](load-test.jmx),\nthe [starter script](run-local.sh) and\nthe example projects ([API Gateway](apigateway), [Example Application](example)).\n\n\n## Getting Started\n\nIn build.gradle.kts (or equivalent), add:\n\n```kotlin\ndependencies {\n    // ...\n    implementation(\"io.github.sunny-chung:spring-starter-feign-coroutine:\u003cversion\u003e\")\n}\n```\n\nSince v0.4.0, it is not compatible with some of the official feign modules, so please also add to the root level of build.gradle.kts:\n```kotlin\nconfigurations.all {\n    resolutionStrategy.eachDependency {\n        if (requested.group == \"io.github.openfeign\" \u0026\u0026 requested.name in setOf(\"feign-kotlin\", \"feign-core\")) {\n            useTarget(\"io.github.sunny-chung:${requested.name}:13.2.1-patch-1\")\n        }\n    }\n}\n```\n\nIf there are multiple Gradle modules within the same project, the resolution can be added to the root build.gradle.kts instead:\n```kotlin\nsubprojects {\n    configurations.all {\n        resolutionStrategy.eachDependency {\n            if (requested.group == \"io.github.openfeign\" \u0026\u0026 requested.name in setOf(\"feign-kotlin\", \"feign-core\")) {\n                useTarget(\"io.github.sunny-chung:${requested.name}:13.2.1-patch-1\")\n            }\n        }\n    }\n}\n```\n\n## Example\n\n```kotlin\n@Configuration\n@EnableCoroutineFeignClients(basePackages = [\"com.sunnychung.example.springfeigncoroutine\"])\nclass FeignConfig {\n    @Bean\n    fun decoder() = JacksonDecoder(jacksonObjectMapper())\n\n    @Bean\n    fun encoder() = JacksonEncoder()\n}\n```\n\n```kotlin\n@CoroutineFeignClient(name = \"svc-a\")\ninterface RemoteApi {\n\n    @PostMapping(\"a\")\n    suspend fun a(@RequestBody req: ApiData): ApiData\n}\n```\n\n```yaml\nspring:\n  cloud:\n    openfeign:\n      client:\n        config:\n          default:\n            default-request-headers:\n              content-type: application/json\n          svc-a:\n            logger-level: full\n            url: http://service-a:8080/api/\n```\n\n```kotlin\n@RequestMapping(\"api\")\nclass ApiController {\n\n    @Autowired\n    lateinit var remoteApi: RemoteApi\n\n    @PostMapping(\"b\")\n    suspend fun b(): ApiData {\n        return remoteApi.a(ApiData(\"b\"))\n    }\n}\n```\n\n## Limitation\nEntire response body is read into memory before next step, this means it would perform not as optimized as\nreactive clients for large response body or streaming.\n\n`Flow\u003cT\u003e` is not yet supported.\n\n## Micrometer Integration\nSimilar to Spring Cloud OpenFeign, just include Micrometer in classpath, then everything is autoconfigured. It can be configured using the same set of application properties.\n\n### Demo\n\nRun the demo servers using `./run-local.sh`, make a cURL request to API gateway which calls service-b which calls service-a.\n\n```\ncurl --verbose \\\n  --request \"POST\" \\\n  --url \"http://localhost:10000/api/b\" \\\n  --header \"Content-Type: application/json\" \\\n  --data \"{\\\"x\\\": 10}\"\n```\n\nThe server log combined in Docker Compose like below is observed:\n\n```\nspring-feign-coroutine-apigateway-1  | 2024-02-24T08:33:12.075Z  INFO 1 --- [ctor-http-nio-2] [65d9a9c86af376b32fea95088ceb267b-2fea95088ceb267b] c.s.e.springfeigncoroutine.LogFilter     : Request -- POST /api/b\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.602Z  INFO 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.s.ApiController                    : API b\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] ---\u003e POST http://service-a:8080/api/a HTTP/1.1\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] Content-Length: 15\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] content-type: application/json\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] \nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] {\nspring-feign-coroutine-service-b-1   |   \"x\" : \"b\"\nspring-feign-coroutine-service-b-1   | }\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:12.608Z DEBUG 1 --- [         task-1] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] ---\u003e END HTTP (15-byte body)\nspring-feign-coroutine-service-a-1   | 2024-02-24T08:33:13.211Z  INFO 1 --- [ctor-http-nio-2] [65d9a9c86af376b32fea95088ceb267b-30c56df6c7d7ee63] c.s.e.s.ApiController                    : API a -- b\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] \u003c--- HTTP/1.1 200 (3724ms)\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] content-length: 11\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] content-type: application/json\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] \nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] {\"x\":\"b a\"}\nspring-feign-coroutine-service-b-1   | 2024-02-24T08:33:16.333Z DEBUG 1 --- [ctor-http-nio-4] [65d9a9c86af376b32fea95088ceb267b-5273a545473a290f] c.s.e.springfeigncoroutine.RemoteApi     : [RemoteApi#a] \u003c--- END HTTP (11-byte body)\nspring-feign-coroutine-apigateway-1  | 2024-02-24T08:33:16.370Z  INFO 1 --- [ctor-http-nio-2] [65d9a9c86af376b32fea95088ceb267b-2fea95088ceb267b] c.s.e.springfeigncoroutine.LogFilter     : Response -- POST /api/b -- 4294ms\n```\n\nNote the traceId (65d9a9c86af376b32fea95088ceb267b) is propagated and consistent.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunny-chung%2Fspring-starter-feign-coroutine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsunny-chung%2Fspring-starter-feign-coroutine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunny-chung%2Fspring-starter-feign-coroutine/lists"}