In the previous parts of this series, we explored how to build AI-powered applications with Spring AI and run models locally. Local inference is great for experimentation, development, privacy-focused use cases, and understanding how LLM applications work.
But production AI systems often need more.
They need access to powerful foundation models, managed infrastructure, scalability, reliability, and the ability to switch between models without managing GPU servers yourself.
This is where AWS Bedrock comes in.
In this article, we'll explore how to integrate AWS Bedrock with Spring AI and move from local AI inference to a managed cloud-based architecture.
AWS Bedrock is a fully managed AWS service that provides access to foundation models from multiple AI providers through AWS infrastructure.
Instead of down and running a model locally, your application sends requests to AWS Bedrock.
The architecture changes from this:
Spring Boot Application
β
Spring AI
β
Local Model Runtime
(Ollama / Local LLM)
To this:
Spring Boot Application
β
Spring AI
β
AWS Bedrock API
β
Foundation Model
Your application no longer needs to manage the underlying AI infrastructure.
AWS handles the model hosting, scaling, availability, and infrastructure required to run inference.
Local models are incredibly useful, but they come with limitations.
For example:
AWS Bedrock solves many of these infrastructure challenges.
With Bedrock, you can focus more on your application instead of managing model servers.
Your architecture becomes more like this:
Client
β
Spring Boot API
β
Spring AI
β
AWS Bedrock
β
Foundation Model
This makes it easier to build cloud-native AI applications.
Spring AI provides abstractions for working with different AI providers.
Your application interacts with high-level APIs such as ChatClient
instead of manually writing HTTP requests for every model provider.
For example:
String response = chatClient.prompt()
.user("Explain AWS Bedrock in simple terms")
.call()
.content();
The application code can remain relatively similar even when the underlying AI provider changes.
For example, you might start with:
Spring AI β Ollama β Local Model
And later move to:
Spring AI β AWS Bedrock β Cloud Model
This abstraction is one of the major advantages of using Spring AI.
Your business logic should ideally depend on AI capabilities rather than being tightly coupled to a specific provider.
Before your Spring Boot application can communicate with AWS Bedrock, you need access to AWS and the required permissions.
At a high level, the process looks like this:
AWS Account
β
Enable Model Access
β
Configure IAM Permissions
β
Configure AWS Region
β
Spring Boot Application
β
Spring AI + AWS Bedrock
The exact models available can vary depending on your AWS region and account configuration.
You also need appropriate AWS credentials and permissions for invoking models.
For local development, credentials can be provided through the AWS credential provider chain, environment variables, profiles, or other supported AWS authentication mechanisms.
A typical environment configuration might look like this:
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=your-region
However, in production, avoid hardcoding credentials in your application configuration.
Prefer IAM roles and managed identity mechanisms whenever possible.
Spring AI provides integrations for AWS Bedrock models.
The dependency you use depends on the specific Spring AI version and Bedrock model integration you want to work with.
For example, your Maven configuration may include a Spring AI AWS Bedrock starter:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-bedrock-converse</artifactId>
</dependency>
Spring AI's dependency management should also be configured using the appropriate BOM for your version.
For example:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>YOUR_SPRING_AI_VERSION</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
The important idea is that Spring Boot auto-configuration can create the required AI components once the correct dependencies and AWS configuration are available.
Your application configuration tells Spring AI how to connect to AWS Bedrock.
A simplified configuration might look something like this:
spring:
ai:
bedrock:
aws:
region: us-east-1
Depending on the Spring AI version and model integration, additional configuration may be required for the selected model, credentials, generation settings, or Bedrock Converse API.
For example, you may configure values such as:
Conceptually:
spring:
ai:
model:
chat: bedrock-converse
bedrock:
aws:
region: us-east-1
The exact property names can vary between Spring AI releases, so always check the documentation for the version you are using.
Once the integration is configured, we can expose a simple API.
First, inject ChatClient.Builder
:
@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
Now a request such as:
GET /api/chat?message=Explain Spring AI
follows this flow:
HTTP Request
β
ChatController
β
ChatClient
β
Spring AI
β
AWS Bedrock
β
Foundation Model
β
Generated Response
β
Spring Boot API
The controller does not need to know the low-level details of the Bedrock API.
Spring AI handles the integration layer.
The most important change is not just replacing one dependency with another.
The architecture itself changes.
User
β
Spring Boot
β
Spring AI
β
Ollama
β
Local LLM
Here, you are responsible for the machine running the model.
You need to think about:
User
β
Load Balancer
β
Spring Boot Application
β
Spring AI
β
AWS Bedrock
β
Foundation Model
Now the model infrastructure is managed separately from your application.
Your Spring Boot application becomes a consumer of AI infrastructure rather than the host of the model itself.
This separation can significantly simplify production architecture.
One major benefit of Bedrock is access to multiple foundation models.
Different models can be better suited for different workloads.
For example:
Chat Application
β
General Model
Document Analysis
β
Long Context Model
Structured Extraction
β
Model with Strong
Structured Output
Complex Reasoning
β
Higher Capability Model
This means model selection becomes an architectural decision.
You should consider factors such as:
The best model is not always the largest or most expensive one.
A production system may even route different requests to different models.
One common mistake is placing model-specific configuration throughout the application.
Instead of this:
if (provider.equals("bedrock")) {
// Bedrock logic
}
if (provider.equals("ollama")) {
// Ollama logic
}
Try to keep provider-specific infrastructure separate from your application logic.
For example:
Application Layer
β
Spring AI Abstraction
β
Provider Configuration
β
AWS Bedrock / Ollama / Other Models
This makes it easier to change providers later.
Your application should ideally focus on:
What should the AI do?
Instead of:
How does this specific provider's HTTP API work?
When working with AWS Bedrock, authentication becomes part of your architecture.
Your application needs permission to invoke models.
For production environments, the preferred approach is generally to use AWS IAM roles instead of embedding access keys inside application properties.
For example:
Spring Boot on AWS
β
IAM Role
β
Temporary Credentials
β
AWS Bedrock
This is safer than:
application.yml
β
Hardcoded AWS Keys
You should also think about:
Moving AI to the cloud also means thinking carefully about what data leaves your application.
With local models, the main cost is often infrastructure.
You pay for:
GPU
RAM
Compute
Storage
Servers
With managed inference, cost is often related to model usage.
Conceptually:
Application Request
β
Input Tokens
+
Output Tokens
β
Inference Cost
This means AI applications should treat token usage as an engineering concern.
You may need:
For example, sending unnecessary context to a model can increase both latency and cost.
A good AI architecture should therefore optimize the entire request pipeline.
Production AI systems need more than application logs.
You may want to monitor:
Request
β
Prompt Size
β
Model
β
Latency
β
Token Usage
β
Cost
β
Response
This helps answer important questions:
As your AI application grows, observability becomes essential.
You don't necessarily need to abandon local models completely.
A practical architecture could use different providers for different environments.
Development
Spring Boot
β
Ollama
β
Local Model
Production
Spring Boot
β
Spring AI
β
AWS Bedrock
β
Cloud Model
This gives developers a fast and inexpensive local development workflow while allowing production to use managed cloud infrastructure.
The important part is keeping your application architecture flexible enough to support both.
AWS Bedrock gives us access to powerful foundation models without managing the underlying AI infrastructure ourselves.
But moving AI into production introduces new challenges.
How do we manage conversation history?
How do we provide the model with our own documents?
How do we build applications that can retrieve relevant information before generating a response?
In Part 7, we'll take the next step and explore RAG with Spring AI.
We'll look at how documents move through the RAG pipeline:
Documents
β
Chunking
β
Embeddings
β
Vector Database
β
Similarity Search
β
Relevant Context
β
LLM
β
Answer
This is where AI applications start becoming truly connected to your own data.
Next up: Building RAG Applications with Spring AI.