How to get InputStream via Spring-Feign?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When you use Spring Cloud OpenFeign to download a file or another large payload, returning a raw InputStream from the client interface is usually not the best approach. The safer pattern is to return Feign's low-level Response or a Spring-friendly wrapper such as Resource, then open and close the stream yourself.
Why Returning InputStream Directly Is Awkward
Feign works by decoding an HTTP response into the declared Java return type. For JSON objects, strings, and small DTOs, that is exactly what you want. For a stream, however, you often need lower-level control over the response body lifecycle.
If the method returns InputStream directly, you depend on the decoder and surrounding infrastructure to keep the body open long enough and in the way you expect. That is brittle. In practice, returning feign.Response gives you direct access to response.body().asInputStream(), which is the most explicit and reliable pattern.
Recommended Feign Client Definition
Here is a straightforward OpenFeign client for file downloads:
The important decision is the return type. Response exposes headers, status, and the response body stream without forcing eager deserialization.
Reading the Stream in a Service
Once you have the raw response, read it in a service layer and close it with try-with-resources.
This approach keeps ownership clear. Your application decides when the stream is consumed and when resources are released.
Alternative: Return a Resource
If you do not need true streaming control and the payload sizes are moderate, returning a Spring Resource can be more idiomatic.
This is convenient for controller passthrough code, but it is less explicit than handling the Feign Response directly. For very large objects or strict resource management, Response is usually the better tool.
Passing the Stream Through a Controller
A common pattern is downloading from one service and relaying the content to the caller.
For huge files, you would normally avoid materializing the whole response as a byte[]. The example is only meant to show the flow from Feign response to controller response.
Common Pitfalls
The most common mistake is forgetting to close the response body. A leaked stream usually means leaked HTTP connections as well.
Another pitfall is reading the entire payload into memory by habit. If the whole reason for using a stream is file size, do not immediately call readAllBytes() in the service layer.
A third pitfall is declaring InputStream directly in the Feign interface and assuming Feign will manage the lifecycle exactly the way you want. It is possible to make that work in some setups, but it is harder to reason about and usually not worth the fragility.
Timeouts also matter. Large downloads often need explicit Feign connect and read timeout tuning, otherwise the stream logic is correct but the call still fails under real network conditions.
Summary
- In Spring Feign, returning
feign.Responseis the most reliable way to access anInputStream - Open the stream with
response.body().asInputStream()and close it with try-with-resources - Use
Resourcewhen you want a higher-level Spring abstraction and the payload is manageable - Avoid reading large responses fully into memory unless that is a deliberate choice
- Treat stream handling and timeout configuration as part of the same download design
Related reading
- How to get largest number of consecutive integers in a substantially large array (spread across multiple machines)
- How to get Memory cost of Distributed Map across node in hazelcast
- How to handle consensus in a decentralized event sourced database?
- How to handle data migrations in distributed microservice databases
- How to get kafka consume lag in java program
- How to get kubernetes service account access token using fabric8 java client?
- How to handle kafka publishing failure in robust way
- How to handle large Swift Project?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.