Spring Boot on AWS Lambda

Your Spring Boot services, starting in about a second.

We move Spring Boot applications onto Lambda. Depending on your code and your team, that means porting the framework layer to Quarkus, compiling Spring Boot to a native binary, or running it on SnapStart. Your business logic stays the same Java.

These numbers are from our September benchmark: Spring Boot on Fargate against Quarkus native on Lambda.

Fargate task startup vs Lambda cold start, measured
54.5 s→684 ms
median latency92.9 ms → 26.6 ms
p99 latency218 ms → 50 ms
memory in use~340 MB → 166 MB
September 2026, us-east-1. Same app, same AWS account, same database, same k6 load.

Options

Four ways to put Spring Boot on Lambda

We ran the same application on Lambda four ways and measured each one. All four handled our load test with no failed requests. Which one we'd recommend depends on your code and your team.

Quarkus native

Port the Spring parts to Quarkus and compile to a native binary. Business logic doesn't change.

Cold start0.65 s
Warm12 ms

Cold starts and cost matter most, and your team is willing to learn Quarkus. It measured best on cold start, warm requests and memory.

Spring Boot native

Stays Spring. Compiled with GraalVM; libraries that use reflection may need hints.

Cold start1.1 s
Warm18 ms

Your team works in Spring, and your CI can handle large native builds (ours peaked at about 11 GB).

Spring Boot on SnapStart, tuned

Stays Spring, on a normal JVM build. We add a request that warms the app before the snapshot, and fix the connection pool.

Cold start1.2 s
Warm21 ms

You want the smallest change, or a library you depend on won't compile native.

Quarkus on SnapStart, tuned

Quarkus on the JVM, so there's no native build to maintain.

Cold start1.4 s
Warm18 ms

You're already on Quarkus but can't run native builds.

SnapStart out of the box took 3.5 s. The snapshot is taken after Spring starts but before it has served a request, so the first real request after a restore loads and runs that code for the first time. Sending one request through the app before the snapshot got it to 1.2 s.

A Spring default cost 30 ms a request. Hibernate can load related rows in batches, but Spring Boot leaves that off, so they come back one query at a time. Quarkus turns it on. Setting one property in Spring, hibernate.default_batch_fetch_size, took warm Spring Boot native requests from about 50 ms to 18.

Measured in October 2026 on one seven-function app in eu-central-1, Lambda arm64 at 1024 MB, under light load (about 35 requests a second). Cold start is the median of Lambda's reported init or restore time plus the first request, over about 360 cold starts per path. Warm is the average server-side duration over two five-minute load runs, with batch fetching on for every path. Full method and what we tuned.

Services

What we deliver

We pick the path with you first, then do the migration, the tuning and the measurement. We use AI for repetitive edits; the diagnosis and the decisions are ours.

01

Lambda Readiness Audit

Before we recommend a path, we read your code and your build pipeline and talk to your team. Libraries that lean on reflection, CI runners too small for a native build, or a team that only knows Spring can each change the answer. You get a written recommendation, with the risks and the numbers we'd expect.

Library & reflection audit · CI build capacity · Team fit

02

Spring Boot → Quarkus Refactoring

AI does the first pass, moving Spring code onto Quarkus extensions: RESTEasy Reactive for the endpoints, Jakarta CDI for injection, Hibernate ORM with Panache for data access. We check every change by hand against the original API. Only the framework layer changes; your business logic stays as it is.

Spring → RESTEasy Reactive · CDI migration · Panache data layer

03

Spring Boot Native & SnapStart Tuning

If the code should stay Spring, we compile it native with GraalVM or run it on SnapStart. Neither does well on defaults: native builds may need reachability hints, SnapStart needs a warm-up before the snapshot and a connection-pool fix, and both need Hibernate batch fetching turned on. In our benchmark, untuned SnapStart answered its first request in 3.5 s. Tuned, 1.2 s.

GraalVM reachability hints · SnapStart priming · CRaC pool handling

04

Architecture Review

A person reviews every migrated service before it ships. We check thread safety, connection pooling, and what happens when Lambda starts many copies at once. These problems show up at runtime, which is why AI tools tend to miss them.

Architecture review · Thread-safety & pooling · Security validation

05

CI/CD & Build Pipeline Integration

We add the new build to the CI/CD you already have, with integration tests and a benchmark check that fails the build when startup or latency gets worse.

Native & SnapStart builds · Integration test coverage · Benchmark gating

06

Monolith Decomposition

If a monolith needs splitting first, we find its domain boundaries and pull services out along them, before or during the move to Lambda. We split our own benchmark app into seven functions this way.

Domain boundary mapping · Service extraction · Independent deploy pipelines

Methodology

We find where
the time goes.

Frameworks are built so you don't have to think about what's underneath: the SQL your ORM writes, the sockets in your connection pool, what the JVM has loaded. That works until something is slow, and then the cause is almost always down there. Years of tracing bottlenecks in production Java taught us to look there first. We measure, trace each slow request to its cause, and measure again. A coding agent will port the annotations, and we use one for that. It won't tell you whether the service should move at all, or that 200 simultaneous cold starts can come back with 2 successes.

Measure·before anything changes
Trace·to the cause, not the symptom
Prove·same benchmark, before and after
01. MeasurePlan

Readiness audit and baseline

We measure your service as it runs today: cold start, latency per endpoint, queries per request, connections held. Then we look for what won't move cleanly, like libraries that rely on reflection or pools sized for long-running containers. That decides which path we recommend. You get a scoped plan, the risks, and the baseline we measure against.

02. MigrateCode

The port or the build change

We do the work for the path you chose: the port to Quarkus, the native build, or the SnapStart setup. AI handles repetitive edits, like moving annotations from one framework to another. Anything that needs judgment, we do ourselves. Where a monolith needs splitting first, we split it along its domain boundaries.

03. TraceFix

Find what is slow, and why

We load-test the migrated service and trace every slow request to its cause: a snapshot taken before any code ran, a query that runs once per row, a pool holding dead connections after a restore. None of these show up as errors, which is why they ship. Finding them is what we have done for years.

04. ProveNumbers

Before and after, on the same infrastructure

Every migration ships with a benchmark against the original service on the same infrastructure: cold start, memory, latency and throughput. The same checks run in CI, so a later change can't quietly undo the gains.

Migration Experience

Spring Boot to Lambda,
without a rewrite

We run Quarkus native in production on our own product, and every engagement starts with the tooling that produced the benchmark on this site. It goes faster than most teams expect, because nearly all of your Java carries over.

Weeks, not months

A typical Spring Boot service should take days to a few weeks, not months. Staying on Spring is mostly build and tuning work. Moving to Quarkus uses standard Java CDI, JAX-RS, and MicroProfile: the same paradigms your team writes today.

The Java carries over

Business logic, domain models and service classes barely change. Injection annotations, REST endpoints and JPA mappings all have direct equivalents.

A written-down process

The playbook covers dependency analysis, finding a replacement for each library, porting integration tests, and verifying the build. The benchmark tooling is the code that produced the numbers on this site.

17native Quarkus services in production
0failures at 350 concurrent users
80×faster cold start, measured (54.5s → 684ms)
~0business logic rewrites needed

Compute Cost

Fargate or Lambda?
Depends on your traffic.

Modeled on our PetClinic benchmark in us-east-1: Spring Boot on ECS Fargate against the same service rebuilt as Quarkus native on Lambda, at published on-demand pricing. Pick a traffic tier or enter your own volume. For the same comparison on a production SaaS API, see what a real SaaS API costs.

Your monthly request volume

A "service" is one Spring Boot deployment you run today, not the Lambda functions it becomes after migration (our reference app split into 7). Assumes services of roughly similar size to the benchmark.

Monthly compute cost, per service

at 5,000,000 requests/month

Spring Boot on Fargate
$72/mo$572/mo total
Quarkus native on Lambda
$6.86/mo$69/mo total

Estimated savings across 10 services

$504/mo

$6,043 per year on compute alone

10 services sharing one load balancer

Priced for Quarkus native. The other tuned paths cost within about 10% more per million requests, because API Gateway is most of the bill.

This covers compute only. Cold starts, database connection limits, and deploying many functions instead of one service are real costs too, and they don't show up here.

Request your free compute assessment

We'll go through what you run today on ECS, Fargate or Lambda and work out what these numbers look like for you. It's free, and you're not committing to anything.

Request free assessment

Preset tiers are modeled from published AWS pricing using the resource usage measured in the benchmark: 2-task Fargate plus ALB against 1024 MB arm64 Lambda plus API Gateway HTTP API, us-east-1 on-demand. Custom volumes use the benchmark's linear Lambda rate and near-fixed Fargate baseline. Several services share one load balancer. A modeled estimate, not a live quote.

PetClinic is a small reference app (0.5 vCPU and 1 GB per task). Production Spring Boot services usually run larger, more expensive Fargate tasks, so the Fargate side here likely understates a real service. The Lambda side has not been benchmarked at that larger scale, so treat the savings as directional.

Case studies

Real numbers, not vendor slides

Two systems we measured ourselves: the AWS benchmark behind our numbers, and a production system we run on the same stack. The method is included for both.

Internal Benchmark

Spring Boot on Fargate vs. Quarkus-native on Lambda

Why: Most Spring Boot services run in always-on JVM containers. We wanted to measure that against a Quarkus native rebuild on Lambda, on the same AWS account, the same database and the same load.

What we found:

We deployed both versions of a reference service (Spring PetClinic) side by side on one AWS account and one database, and load-tested them identically. The native rebuild was faster at every percentile, not only in the tail, and two details of the setup cut against our own result. The full write-up covers both, with every raw figure.

Full method and raw figures
Cold start
54.5s (Fargate)→684ms (Lambda)
Median latency
92.9ms (Fargate)→26.6ms (Lambda)
p99 latency
218ms (Fargate)→50ms (Lambda)
100K req/mo
$55 (Fargate)→$0.14 (Lambda)
5M req/mo
$72 (Fargate)→$6.86 (Lambda)
50M req/mo
$190 (Fargate)→$69 (Lambda)

Own Product

duty27.com: 17 native services, zero idle cost

Why: The benchmark above tests one reference app. We wanted to know whether the approach holds up in a real multi-tenant SaaS, with auth, billing and compliance workflows.

What we found:

duty27.com is our own EU VAT-compliance platform, built and run by us end to end: 17 independently-deployed Quarkus services, every one compiled to a native ARM64 binary on AWS Lambda. That covers a custom JWT authorizer, Stripe billing, and VIES VAT-validation workflows. A Tailscale-gated admin console handles client management: entitlements, transaction and VIES-history lookups, access revoke/restore, GDPR deletion, and broadcast messaging.

We load-tested it the same way as the benchmark above: 50 concurrent virtual users against prod, 10 real client accounts, running VAT calculation’s full request chain: JWT auth, entitlement checks, a cross-Lambda VAT-rate/VIES lookup. 7,294 calls in 4 minutes, zero failures, p95 278ms; that is well above the benchmark’s 36.9ms p95 because each duty27 request does all three of those steps, where the benchmark measured a single-table read.

After fixing a throttle limit that only surfaced under heavier concurrency, we pushed it further: 350 VUs, 7× the original load, for a 2-minute hold. 51,411 requests, all 200 OK, zero failures, zero throttling, ~186 req/sec sustained, and p95 latency dropped slightly, to 246ms.

Thirty days of real CloudWatch data puts total traffic at ~140K invocations across all 17 functions, well inside Lambda’s monthly free tier. Modeled on Fargate at the same always-on 2-task-plus-load-balancer baseline as the benchmark above, that footprint runs $75–$95 a month, paid whether or not a single request arrives. On Lambda we pay per request, and nothing while it’s idle.

Independent Quarkus services
built from scratch→17
Native ARM64 across the stack
0→17 of 17
k6 load test, 50→350 VUs (7× scale-up)
278ms p95→246ms p95, 0 failures
Monthly compute at real prod traffic
$75–$95 (Fargate-equivalent)→pay-per-invocation, $0 idle

Who you'd work with

James Frisch

Founder · Principal software engineer · San Francisco Bay Area

I build and operate Duty27, a live EU VAT-compliance API: correct VAT rates by country, date and category, plus B2B reverse-charge validation against the EU's VIES service. I built it and run it by myself.

The backend is 17 independently deployable AWS Lambda services written in Java with Quarkus and compiled to GraalVM native images on ARM64, with Cognito authentication, Stripe billing, and CloudFormation and SAM infrastructure as code across isolated dev and production environments. I load-tested it to 350 concurrent users, seven times its baseline, with zero failures and p95 latency held flat at 246ms.

Most of my career has been finding where the time goes. One example: a traffic feed arrived every five minutes, and the code that transformed it for the routing software took six to seven minutes to run, so routes were always built on stale conditions. It processed every record in one serial loop. I moved it onto messaging so the records were handled in parallel, and the same work finished in under a second.

The rest has been building new systems. I've chosen the stack for many companies, including Aerion and Partnerly, so the decisions this site is about are ones I've made, not just inherited.

I publish measurements, including the ones that weaken my own case. In the benchmark on this site, Lambda served HTTPS while Fargate served plain HTTP, and the write-up says so.

I use AI agents heavily, to research a codebase, audit infrastructure, and check claims against what the live system returns before anything ships. They speed up the legwork. I review everything they produce, and the judgment calls are mine.

Full profile on LinkedIn

Track record

2026–
Duty27
Founder and architect
2024–25
Partnerly Homes
Head of Engineering
2021–23
SambaSafety
Senior Software Engineer
2020–21
Club Connection
Co-founder, lead architect
2018–20
JPMorgan Chase, via Artech
Senior Consultant
2013–18
Aerion Technologies
Head of Software Production
2008–13
Eveo
Director of Engineering

Regulated domains throughout: pharma, financial services, aerospace, EU tax compliance.

Contact

Start with a
free assessment

Every engagement starts with a free technical assessment. We look at your Spring Boot services, work out which ones are worth moving and which path fits, and send a written recommendation. Sometimes that recommendation is to leave a service where it is. Where a move is worth it, you get a scoped proposal with the expected cost and performance change. You don't commit to anything until then.

Free 2-hour codebase assessment
Scoped proposal within 5 business days
No commitment until you approve the plan

Used only to reply to you. Privacy policy