Feign turns annotations into HTTP requests for text-based APIs
Feign makes writing java http clients easier
At a glance
- What is it?
- Feign binds a Java interface to an HTTP API by turning annotations into a templatized request and applying arguments before output. The library covers text-based APIs, leaves binary and streaming protocols out, and its roadmap still carries caching, retry and reactive work while releases have reached 13.17.
- Who is it for?
- Use Feign when your Java service calls a text-based HTTP API and you would rather declare an interface than hand-write a client, accepting that the contract is positional. Do not pick it for binary protocols, streaming bodies, or built-in response caching or reactive execution, since those sit on the roadmap rather than in the released artifact.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- OpenFeign/feign9,798 ★ · -2
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| OpenFeign/feign | 9.8k | 9.8k |
-2 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The Maven snippet in the README still carries an unresolved version token
The library is distributed through Maven Central under io.github.openfeign, and the coordinates in the usage section are these:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>??feign.version??</version>
</dependency>The version element is a template token that was never substituted, so the snippet as printed is not a buildable declaration. Recent releases move fast enough that the choice matters: 13.17 was published on 2026-10-08, 13.16 on 2026-10-05, and 13.15 on 2026-09-09. Consequence for you: you fill in the version yourself, and you pick the decoder module yourself, because nothing here tells you that feign-core binds templates but does not map a response body to your own types.
The basics sample ends mid-token, before the client is ever constructed
The basics section shows an interface, an adaptation of the canonical Retrofit sample:
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);The sample also defines a Contributor class, an Issue class, and the opening of a main method. The declared shape is complete: each method carries an @RequestLine with an HTTP verb and a URI template, curly-brace expressions resolve from @Param annotated parameters, and a POST method takes a body object alongside two path variables.
An unnamed @Param depends on bytecode parameter names and the -parameters flag
Feign's default contract defines six annotations, and the @Param entry has a detail that bites teams that rename parameters. It defines a template variable whose value resolves the matching template expression by name given as the annotation value, and when that value is missing it tries to read the name from the bytecode method parameter name, which exists only if the code was compiled with the -parameters flag. The other five are @RequestLine on a method, defining the HTTP method and the URI template, @Headers on a method or a type, defining a header template applied to every request when placed on a type, @QueryMap on a parameter, expanding a Map of name value pairs or a POJO into a query string, @HeaderMap on a parameter, expanding a Map into HTTP headers, and @Body on a method. Consequence for you: in a build without that compiler flag, every @Param needs an explicit value or the expression has nothing to resolve to, and the failure appears at call time rather than at compile time.
Per request host targeting rides as a positional java.net.URI parameter
There is no annotation for pointing a single call at a different server than the one the client was built for. The documented approach is to include a java.net.URI parameter, and Feign uses that value as the request target:
@RequestLine("POST /repos/{owner}/{repo}/issues")
void createIssue(URI host, Issue issue, @Param("owner") String owner, @Param("repo") String repo);That host parameter carries no annotation value of its own, so it is matched by position rather than by name, unlike the @Param variables in the same signature. This is also the escape hatch for a client that must talk to several backends, which is the usual case in a service that fans out to per-tenant or per-region endpoints. Consequence for you: reordering arguments in one of these methods changes behavior without any compile error, and a client with a fixed host gives you no way to override it except by declaring the URI parameter, so decide early whether signatures carry one.
Text-based APIs are the stated boundary, and the workaround is your own code
The scope is stated in plain terms: Feign is limited to supporting text-based APIs. Its mechanism is annotation processing into a templatized request, with arguments applied to those templates before output, which is what makes replaying requests and unit testing your conversions straightforward. Around that core the project uses tools like Jersey and CXF to write Java clients for ReST or SOAP services, and it lets you write your own code on top of HTTP libraries such as Apache HC, with customizable decoders and error handling that can be pointed at any text-based HTTP API. Consequence for you: binary payloads, streaming uploads, long-lived connections, and anything that is not a text request body fall outside the design, and the documented path for them is your own client code beside Feign rather than a Feign feature. Async and reactive are on the roadmap, so a CompletableFuture or Reactive Streams client is not something the current artifact gives you.
The roadmap header reads Feign 11 and beyond while releases sit at 13.15
The feature map in the README introduces itself as a map of current key features and is followed immediately by a roadmap headed Feign 11 and beyond, which is worth weighing against releases 13.15, 13.16, and 13.17 from September and October 2026 and a last push on 2026-11-02. On that roadmap, response caching is short term work, in memory plus external mechanisms such as EhCache, Google, and Spring, along with full level 1 through level 4 URI template expressions verified against the URI Templates TCK, a Logger API refactor toward the shape frameworks like SLF4J use, and a Retry refactor for user supplied conditions and back off control that is flagged as possibly breaking. Async execution via CompletableFuture is medium term and is called out as required before reactive execution, and reactive support targets java.util.concurrent.Flow on JDK 9 plus Project Reactor and RxJava 2+ on JDK 8. Additional circuit breakers such as Resilience4J sit in the long term column. Consequence for you: caching, complete template level coverage, and a settled retry and logging API are planned rather than delivered, so build your own policy layer instead of waiting.
Decoders, HTTP clients, and integrations each cost a separate module
The repository is a multi module build, and the top level shows how wide the surface is. Serialization arrives in pieces: jackson/, jackson3/, gson/, moshi/, json/, and fastjson2/, with jackson-jaxb/ for the JAXB combination. Transport is separate again, with okhttp/, hc5/, httpclient/, and googlehttpclient/. Beyond that sit form/ and form-spring/, the JAX-RS modules jaxrs/, jaxrs2/, jaxrs3/, and jaxrs4/, jaxb/ and jaxb-jakarta/, jakarta/, java11/, kotlin/, hystrix/, reactive/, graphql/ and graphql-apt/, mock/, micrometer/, dropwizard-metrics4/, dropwizard-metrics5/, http-cache/, and annotation-error-decoder/. Build infrastructure lives alongside them in pom.xml, mvnw, mvnw.cmd, .mvn/, .circleci/, and .github/, with contributor and release notes in HACKING.md, RELEASE.md, SECURITY.md, AGENTS.md, CHANGELOG.md, and CONTRIBUTING.md. Sample modules include example-github/, example-github-with-coroutine/, example-wikipedia/, and example-wikipedia-with-springboot/. Consequence for you: each choice of decoder and client is an extra dependency to version, and picking none leaves you with a binder and no body mapping.
The stated Java floor is 8, and JDK 6 users are pushed to the 9.x line
The compatibility statement is short and split by major version. Feign 10.x and above are built on Java 8 and should work on Java 9, 10, and 11. For anyone who still needs JDK 6 compatibility, the instruction is to use Feign 9.x. The line you must verify is your own runtime against the version you pin. The presence of a java11/ module and a jakarta/ set of modules shows that JDK and namespace differences were tracked as separate concerns rather than folded into core. Consequence for you: on an old JDK you are not choosing a configuration, you are choosing an old major version, and on a current JDK you should confirm the combination yourself before making it a dependency of a service.
Editorial conclusion
Use Feign when your Java service calls a text-based HTTP API and you would rather declare an interface than hand-write a client, accepting that the contract is positional. Do not pick it for binary protocols, streaming bodies, or built-in response caching or reactive execution, since those sit on the roadmap rather than in the released artifact. Before you start, substitute a real version into the Maven coordinate, because the published snippet still carries an unresolved placeholder, and add the decoder module that matches your payload, since feign-core alone binds templates but does not map bodies. Compile with -parameters if you rely on unnamed @Param values, and pin the version, since the planned Retry API refactor is flagged as a possible breaking change.
Frequently asked questions
what is feign client
Feign is a Java to HTTP client binder. You declare an interface whose methods carry annotations such as @RequestLine and @Param, and Feign turns those annotations into a templatized request, applies the arguments, and hands the result to customizable decoders and error handling.
how to use feign client
Declare an interface with @RequestLine on each method, use curly-brace expressions in the path, bind them with @Param, and add @Body, @Headers, @QueryMap, or @HeaderMap where you need a payload, headers, or a query string. These six annotations are what Feign's default contract defines.
how to add feign client dependency
The usage section gives Maven coordinates for io.github.openfeign:feign-core from Maven Central, but the printed snippet leaves the version element as an unresolved token, so you must substitute a concrete version yourself.
how to use feign client in spring boot
The repository contains an example-wikipedia-with-springboot module, alongside example-github/ and example-github-with-coroutine/.
how to use feign client in microservices
Feign's stated first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness. It uses tools like Jersey and CXF for ReST or SOAP services, and it lets you put your own code on HTTP libraries such as Apache HC underneath.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openfeign-feign)Star history chart for your README
[](https://hysenlabs.com/projects/openfeign-feign)Was this useful?