Running LLM Inference on AWS - Bedrock vs SageMaker vs Self-Hosted on EKS
When to use each option - a decision framework
Before comparing pricing, architecture, and operational overhead, here is the fundamental question: what are you optimising for?
- Bedrock - you want zero infrastructure management, pay only for what you use, and need access to frontier models (Claude Sonnet 4.6/5, Opus 4.6/4.8, Llama 3, Mistral) without managing GPUs
- SageMaker - you need fine-tuned models, custom containers, or dedicated capacity with predictable latency guarantees
- Self-hosted on EKS - you require full control over the inference stack, run open-source models (Llama, Mixtral, Qwen), or need to minimise per-token costs at high volume
In practice, many teams use a combination: Bedrock for prototyping and low-volume production, SageMaker for fine-tuned models, and EKS for high-throughput batch inference. The architecture is not mutually exclusive.
AWS Bedrock - architecture, pricing, and limitations
How Bedrock works
Bedrock is a fully managed service. You send a request (prompt + parameters), AWS routes it to the model provider’s infrastructure, and you receive a response. There are no instances to provision, no GPUs to manage, and no cold starts for on-demand inference.
The request flow:
- Your application calls the Bedrock
InvokeModelorConverseAPI - AWS routes the request to the appropriate model endpoint (within the same region)
- The model processes the prompt and returns tokens
- You pay per input token processed and per output token generated
Bedrock pricing breakdown
Bedrock charges per 1,000 tokens (roughly 750 words). Pricing varies significantly by model:
| Model | Input (per 1K tokens) | Output (per 1K tokens) | eu-west-2 In-Region | Notes |
|---|---|---|---|---|
| Claude Sonnet 5 | $0.003 | $0.015 | EU Geo only | Latest, best quality/cost ratio |
| Claude Sonnet 4.6 | $0.003 | $0.015 | Yes | Available in-region in London |
| Claude Opus 4.8 | $0.005 | $0.025 | EU Geo only | Highest capability, reasoning-intensive |
| Claude Opus 4.6 | $0.005 | $0.025 | Yes | Available in-region in London |
| Claude Haiku 4.5 | $0.001 | $0.005 | EU Geo only | Fast, cheap, classification/extraction |
| Claude 3.5 Haiku | $0.0008 | $0.004 | Yes | In-region London, legacy but available |
| Llama 3 70B Instruct | $0.00099 | $0.00099 | Yes | Open-weight, in-region London |
| Llama 3 8B Instruct | $0.00022 | $0.00022 | Yes | Smallest, cheapest in-region option |
| Mistral Large | $0.002 | $0.006 | Yes | Strong multilingual, in-region London |
| Amazon Nova Pro | $0.0008 | $0.0032 | Yes | AWS-native, good for RAG |
Important for UK organisations: Models marked “EU Geo only” use Bedrock’s Geographic routing - your prompts and responses stay within EU boundaries but may be processed in any EU region (Frankfurt, Ireland, Paris, London). If your compliance requirement is strictly “data must not leave the UK” (rather than “data must stay in EU”), you are limited to models with in-region support. For most UK GDPR purposes, EU Geo routing is acceptable since it satisfies data adequacy requirements.
For Provisioned Throughput, Bedrock offers committed capacity billed per model unit per hour. This makes sense when you have predictable, high-volume workloads and need guaranteed throughput without throttling.
Example cost calculation: a customer support chatbot handling 10,000 conversations/day with an average of 500 input tokens and 200 output tokens per turn, using Claude 3.5 Haiku (available in-region in London):
- Input: 10,000 x 500 / 1,000 x $0.0008 = $4.00/day
- Output: 10,000 x 200 / 1,000 x $0.004 = $8.00/day
- Monthly total: approximately £290 (around $360)
That is remarkably cheap for a production AI system with no infrastructure to manage.
When Bedrock is the right choice
- Inference volume under 50,000 requests/day
- You need frontier model quality (Claude Sonnet 5, Opus 4.8, or Llama 4 via Geo routing) without managing hardware
- UK data residency requirements satisfied by eu-west-2 (London region) availability
- Rapid prototyping where time-to-production matters more than per-token cost
- Teams without ML infrastructure expertise
Limitations
- No fine-tuning for most models - Bedrock supports fine-tuning only for select models (Titan, some Llama variants). For custom models, SageMaker is required.
- Region availability - strict in-region availability in eu-west-2 (London) is limited to Claude Sonnet 4.6, Claude Opus 4.6, Claude 3.5 Haiku, and Llama 3 70B/8B Instruct. Newer models (Sonnet 5, Opus 4.8, Haiku 4.5, Llama 4) are available via EU Geographic routing - your data stays within EU boundaries but may be processed in Frankfurt, Ireland, or Paris rather than strictly in London. For organisations requiring strict single-region processing in the UK, this distinction matters. Always verify current status in the Bedrock region compatibility page.
- Throughput limits - default quotas can throttle high-volume production workloads. Request quota increases proactively.
- No streaming control - limited ability to tune batch sizes, quantisation, or inference parameters beyond what the API exposes.
Official Bedrock pricing documentation: aws.amazon.com/bedrock/pricing
SageMaker Endpoints - architecture, pricing, and when to choose
Inference endpoint types
SageMaker offers three inference patterns:
- Real-time endpoints - always-on instances serving synchronous requests. Best for low-latency production APIs.
- Serverless inference - automatically scales to zero, provisions capacity on demand. Good for sporadic traffic but with cold start penalty (10-60 seconds).
- Asynchronous inference - queues requests and processes them in the background. Ideal for batch jobs and long-running generation tasks.
Pricing model
SageMaker charges per instance-hour for real-time endpoints. You pay for the instance whether it is processing requests or idle.
| Instance Type | GPU | GPU Memory | Hourly Cost (eu-west-2) | Typical Use |
|---|---|---|---|---|
| ml.g5.xlarge | 1x A10G | 24 GB | ~$1.41/h | 17B models (quantised) |
| ml.g5.2xlarge | 1x A10G | 24 GB | ~$1.89/h | 17B models with larger batch |
| ml.g5.12xlarge | 4x A10G | 96 GB | ~$7.09/h | Larger models (tensor parallel) |
| ml.p4d.24xlarge | 8x A100 | 320 GB | ~$37.69/h | Large models, high throughput |
| ml.inf2.xlarge | 1x Inferentia2 | 32 GB | ~$0.76/h | Optimised inference (compiled models) |
Example cost calculation: running a fine-tuned Llama 3 8B on ml.g5.xlarge 24/7:
- $1.41/h x 720 hours = $1,015/month
- Monthly total: approximately £810 (around $1,015)
Compare this to Bedrock: if you are processing more than ~250,000 requests/month with average 500-token prompts, SageMaker becomes cheaper than Bedrock on a per-request basis.
When SageMaker wins
- You have fine-tuned a model and need to serve it
- Predictable, sustained traffic (the instance runs efficiently at 60-80% utilisation)
- You need control over batch size, quantisation (GPTQ, AWQ), and serving framework
- Latency SLAs require dedicated capacity without cold starts
- Compliance requires running in a VPC with no shared infrastructure
Autoscaling configuration
SageMaker supports target-tracking autoscaling. A practical configuration:
# SageMaker endpoint autoscaling based on invocations per instance
import boto3
client = boto3.client("application-autoscaling")
# Register the endpoint variant as a scalable target
client.register_scalable_target(
ServiceNamespace="sagemaker",
ResourceId="endpoint/llm-production/variant/AllTraffic",
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
MinCapacity=1,
MaxCapacity=8,
)
# Scale based on invocations per instance (target: 100 concurrent)
client.put_scaling_policy(
PolicyName="llm-invocations-scaling",
ServiceNamespace="sagemaker",
ResourceId="endpoint/llm-production/variant/AllTraffic",
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
PolicyType="TargetTrackingScaling",
TargetTrackingScalingPolicyConfiguration={
"TargetValue": 100.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "SageMakerVariantInvocationsPerInstance"
},
"ScaleOutCooldown": 60, # seconds before scaling out again
"ScaleInCooldown": 300, # seconds before scaling in (conservative)
},
)
Official SageMaker pricing documentation: aws.amazon.com/sagemaker/pricing
Self-Hosted on EKS - architecture for teams that need full control
Why self-host?
Self-hosting LLM inference on EKS makes sense when:
- You run open-source models (Llama 4, Mixtral, Qwen, Phi) and want to eliminate per-token API costs entirely
- Inference volume is high enough (>100K requests/day) that compute cost per token drops below managed service pricing
- You need custom serving frameworks (vLLM, Text Generation Inference, Triton)
- Multi-model serving on shared GPU infrastructure reduces overall cost
- You already operate EKS and have GPU scheduling expertise
Architecture components
A production self-hosted LLM stack on EKS typically includes:
- GPU node pools - managed node groups or Karpenter-provisioned nodes with NVIDIA GPUs
- Inference server - vLLM, Hugging Face TGI, or NVIDIA Triton serving the model
- Autoscaler - Karpenter for node-level scaling, HPA/KEDA for pod-level scaling
- Load balancer - ALB/NLB with gRPC or HTTP/2 support
- Model storage - S3 + FSx for Lustre or EBS for fast model loading
- Monitoring - Prometheus + Grafana tracking GPU utilisation, queue depth, latency percentiles
GPU instance costs on EC2 (for EKS nodes)
| Instance | GPU | VRAM | On-Demand (eu-west-2) | Spot (typical) | Models it can run |
|---|---|---|---|---|---|
| g5.xlarge | 1x A10G | 24 GB | ~$1.01/h | ~$0.40/h | Scout/Maverick 17B (quantised) |
| g5.2xlarge | 1x A10G | 24 GB | ~$1.21/h | ~$0.48/h | 17B full precision |
| g5.12xlarge | 4x A10G | 96 GB | ~$5.67/h | ~$2.27/h | Larger models (tensor parallel) |
| g6.xlarge | 1x L4 | 24 GB | ~$0.98/h | ~$0.39/h | Scout/Maverick 17B (good inference/watt) |
| p5.48xlarge | 8x H100 | 640 GB | ~$98.32/h | ~$39.33/h | 405B models, training |
The cost advantage of self-hosting comes from two factors: (1) GPU spot instances at 60-70% discount, and (2) high utilisation through request batching and multi-model serving.
Karpenter NodePool for GPU spot instances
# Karpenter NodePool for LLM inference GPU nodes
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: llm-inference-gpu
spec:
template:
metadata:
labels:
workload-type: llm-inference
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodes
requirements:
- key: "karpenter.k8s.aws/instance-family"
operator: In
values: ["g5", "g6"]
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"] # prefer spot, fall back to on-demand
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
taints:
- key: nvidia.com/gpu
effect: NoSchedule # only GPU workloads land here
limits:
cpu: "128"
memory: "512Gi"
nvidia.com/gpu: "16" # max 16 GPUs across all nodes
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m # reclaim idle GPU nodes quickly
weight: 10 # prefer this pool for GPU pods
vLLM deployment on EKS
# Kubernetes Deployment for vLLM serving Llama 4 Scout 17B
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-llama-8b
namespace: inference
spec:
replicas: 2
selector:
matchLabels:
app: vllm-llama-8b
template:
metadata:
labels:
app: vllm-llama-8b
spec:
nodeSelector:
workload-type: llm-inference
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- "--model"
- "meta-llama/Llama-4-Scout-17B-Instruct"
- "--tensor-parallel-size"
- "1"
- "--max-model-len"
- "8192"
- "--gpu-memory-utilization"
- "0.9"
ports:
- containerPort: 8000
name: http
resources:
limits:
nvidia.com/gpu: "1"
memory: "32Gi"
requests:
nvidia.com/gpu: "1"
memory: "24Gi"
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 120 # model loading takes time
periodSeconds: 10
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: token
Cost model for self-hosted inference
Example: serving Llama 4 Scout 17B on 2x g5.xlarge spot instances (24/7):
- 2 x $0.40/h x 720 hours = $576/month
- Add EKS cluster fee: $73/month
- Add ALB: ~$25/month
- Monthly total: approximately £540 (around $674)
At a typical throughput of 30 tokens/second per GPU, this handles roughly 50,000-80,000 requests/day with average 200-token outputs. The per-request cost is effectively £0.000007 - orders of magnitude cheaper than Bedrock at this scale.
Cost comparison across scenarios
| Scenario | Bedrock (Claude 3.5 Haiku) | SageMaker (g5.xlarge) | EKS Self-Hosted (g5.xlarge spot) |
|---|---|---|---|
| Low volume (1K req/day, ~500 tokens each) | ~£29/month | ~£810/month (over-provisioned) | ~£540/month (over-provisioned) |
| Medium volume (50K req/day) | ~£1,450/month | ~£810/month (1 instance) | ~£540/month (2 spot instances) |
| High volume (500K req/day) | ~£14,500/month | ~£4,860/month (6 instances) | ~£1,620/month (6 spot instances) |
The crossover point where self-hosting becomes cheaper than Bedrock is typically around 10,000-20,000 requests/day, depending on the model and token length. Below that, Bedrock’s zero-infrastructure overhead is hard to beat.
Latency and performance comparison
| Metric | Bedrock | SageMaker (dedicated) | EKS Self-Hosted (vLLM) |
|---|---|---|---|
| Time to first token (p50) | 200-400ms | 100-200ms | 50-150ms |
| Time to first token (p99) | 800-1500ms | 300-500ms | 200-400ms |
| Tokens/second (generation) | 30-80 t/s | 20-60 t/s | 30-80 t/s (tuneable) |
| Cold start | None (on-demand) | 5-10 min (new instance) | 2-5 min (model loading) |
| Throughput ceiling | Account quota limited | Instance count limited | GPU count limited |
Bedrock’s latency is acceptable for most interactive applications. For latency-critical paths (real-time trading signals, sub-100ms requirements), self-hosted inference with warm GPU pools is the only viable option.
Decision matrix
| Factor | Choose Bedrock | Choose SageMaker | Choose EKS Self-Hosted |
|---|---|---|---|
| Team size | No ML infra engineers | 1-2 ML engineers | Dedicated platform team |
| Volume | <50K requests/day | 10K-200K requests/day | >100K requests/day |
| Model | Frontier (Claude, Llama hosted) | Fine-tuned or custom | Open-source (self-served) |
| Latency SLA | p99 < 2s acceptable | p99 < 500ms needed | p99 < 200ms critical |
| Compliance | Shared infra acceptable | Dedicated VPC needed | Full isolation required |
| Cost priority | Simplicity over savings | Predictable spend | Lowest per-token cost |
Deploying Bedrock in eu-west-2 for UK organisations
For organisations subject to UK GDPR or FCA oversight, data residency is a primary concern. AWS Bedrock offers two routing options relevant to UK deployments:
- In-Region (strict London): Your requests stay entirely within eu-west-2. Available models: Claude Sonnet 4.6, Claude Opus 4.6, Claude 3.5 Haiku, Llama 3 70B/8B, Mistral Large, Amazon Nova. Use when regulations require strict single-region UK processing.
- EU Geographic routing: Requests are processed within EU boundaries (London, Frankfurt, Ireland, Paris) for higher throughput. Available models: Claude Sonnet 5, Opus 4.8, Haiku 4.5, and other latest releases. Acceptable for most UK GDPR purposes since EU adequacy decisions apply.
Key considerations:
- Model availability vs compliance trade-off - the newest, most capable models (Sonnet 5, Opus 4.8) require EU Geo routing. If you strictly need in-region London, Claude Sonnet 4.6 is your best option - same pricing tier, slightly older model.
- VPC endpoints - deploy a Bedrock VPC endpoint to ensure API calls never traverse the public internet
- CloudTrail logging - all Bedrock API calls are logged, supporting audit requirements
- No data retention - Bedrock does not store or train on your prompts/responses (unless you explicitly opt into model evaluation)
Scaleups across Manchester’s growing AI corridor and Edinburgh’s fintech ecosystem face this architecture decision as inference volumes grow beyond prototype stage. The infrastructure choice made at 1,000 requests/day rarely survives 100,000 - planning the migration path early saves significant rework.
Frequently asked questions
Is Bedrock cheaper than running my own GPUs?
At low-to-medium volumes (under ~20,000 requests/day with average-length prompts), yes. Bedrock eliminates the baseline cost of keeping GPU instances running 24/7. Above that threshold, self-hosted inference on spot instances becomes significantly cheaper per token.
Can I use Bedrock and self-hosted together?
Yes - this is a common pattern. Use Bedrock for low-volume, high-quality tasks (complex reasoning, customer-facing chat) and self-hosted inference for high-volume, cost-sensitive tasks (classification, extraction, embeddings). Route requests based on task complexity.
What about SageMaker Serverless Inference for LLMs?
SageMaker Serverless Inference has cold starts of 10-60 seconds for GPU workloads, making it impractical for interactive LLM serving. It works for batch processing or very infrequent inference, but real-time endpoints or Bedrock are better for production chat/API scenarios.
How do I handle GPU spot interruptions on EKS?
Karpenter automatically replaces interrupted spot instances. For inference (stateless), this means a brief capacity dip (30-120 seconds) while a new node provisions. Mitigation strategies: run across multiple instance types and AZs, maintain a small on-demand baseline (1-2 nodes), and use pod disruption budgets to ensure minimum replica count.
What GPU should I start with for a 7B model?
A single g5.xlarge (A10G, 24GB VRAM) comfortably runs Llama 4 Scout 17B or Mistral 7B with AWQ/GPTQ quantisation. For larger models, you need g5.12xlarge (4x A10G, 96GB total) with tensor parallelism, or a single p4d instance. Start small, measure throughput, and scale horizontally.
Summary
- Bedrock is the right default for teams starting with LLM inference. Zero operational overhead, pay-per-token, and available in eu-west-2 for UK data residency. Best for volumes under 50K requests/day.
- SageMaker fills the gap for fine-tuned models and predictable workloads where you need dedicated capacity without managing Kubernetes. Cost-effective at medium volumes with autoscaling.
- Self-hosted on EKS delivers the lowest per-token cost at scale, but requires GPU scheduling expertise, Karpenter configuration, and operational maturity. The 60-80% cost reduction over managed services justifies the investment above 100K requests/day.
- The crossover point between Bedrock and self-hosted is typically £1,000-£1,500/month in Bedrock spend. Below that, the operational simplicity of Bedrock wins. Above it, start planning your EKS GPU infrastructure.
- For retrieval-augmented generation workloads where inference is just one component, see our guide to RAG infrastructure on AWS.
Need help designing your LLM inference architecture or optimising costs for an existing deployment? The Devopsity engineering team helps organisations across the UK move from prototype to production AI infrastructure. Get in touch to discuss your specific requirements.