Hire Java Developers: Costs, Spring Boot Signals and Vetting
Expect $25 to $55 per hour offshore, $50 to $95 per hour for strong Eastern European or Latin American Java engineers, and $100 to $175 per hour onshore in the US or UK for senior Spring Boot people, based on what Digital Heroes bills and the deals we compete for. For most companies the recommendation is staff augmentation or an agency pod, because Java work is rarely one person's job: the person who writes the Spring Boot service, the person who tunes the JVM under load, and the person who untangles a legacy JPA data model are usually not the same human. Hire in-house only when the JVM platform is the product and you will feed it work for years.
"Java developer" covers at least four different jobs
Java hiring goes wrong because the word is too broad. There is the Spring Boot service developer building REST APIs, wiring up Spring Data JPA repositories, and shipping to a container. There is the platform person who knows why your G1 pauses spike at 4pm and how to read a heap dump. There is the integration engineer who lives in Kafka consumers, message ordering and idempotency. And there is the legacy specialist who can walk into a fifteen year old Struts or EJB codebase, or a WebLogic monolith with an Ant build, and not quit in week two.
The pattern that follows is familiar. A company hires a Java developer with a clean CV: eight years, Spring Boot, microservices, all the right nouns. He ships features fine for two months. Then the first real traffic day arrives and the checkout endpoint starts timing out. The database looks idle. CPU is fine. He restarts pods and it goes away for an hour, then comes back. What was actually happening: a Spring Data JPA repository call inside a loop, lazy loading a collection per row, so one page view fired 400 queries. Classic N+1. The connection pool was on HikariCP defaults, ten connections, and every request was parked waiting for one. He had never used Hibernate statistics logging, had never turned on spring.jpa.show-sql in a staging profile, and had no idea that @Transactional on the service method was holding a connection open across an HTTP call to a payment provider. None of that is exotic. It is the bread and butter of production Java. He had simply spent eight years in a shop where a senior architect made those decisions and he wrote controllers.
That is the core hiring risk in this stack. Java has been around long enough that a developer can accumulate a decade of experience while never once being the person who diagnosed something. The framework hides a lot. Spring in particular is so good at wiring things together that plenty of people write Java for years without understanding what the container is doing on their behalf. When something breaks below the annotation layer, they are stuck, and you find out at the worst possible moment.
The second failure mode is version drift. Someone whose real experience stops at Java 8 will write Java 8 in your Java 21 codebase. No records, no sealed interfaces, no pattern matching in switch, no var, no text blocks, and definitely no virtual threads. That is not a style complaint. It means they will hand roll things the language now does for them, and they will make threading decisions on a mental model that Project Loom already changed. Ask directly what Java version their last three projects ran on. The answer is often more revealing than the whole CV.
Engagement models: what each one is actually good for
In-house hire. Right when Java is your permanent backbone: a core banking system, an order management platform, an internal service mesh other teams build on. You need someone who accumulates knowledge of your domain and your quirks. The cost is not just salary, it is the recruiting cycle, the ramp, and the fact that a single Java hire almost never covers the full surface. One person who is great at Spring Boot APIs is usually mediocre at JVM tuning and knows nothing about your Kafka topology.
Freelancer. Genuinely good for bounded, well specified work. A Spring Boot service with a clear contract. A migration from Java 8 to Java 17 where the acceptance criteria are that the build passes and the tests are green. An integration with a third party API. Freelancers fall apart when the work needs someone to own decisions over time, or when the codebase is old and gnarly enough that context transfer costs more than the work itself. They also disappear. If your production Java is maintained by one contractor who takes a full time job, you have a problem you will discover during an incident.
Agency. Right when you want the outcome and not the management. You describe what the system needs to do, someone else figures out whether it needs Spring Boot or Quarkus, whether the persistence layer should be JPA or jOOQ, how the CI pipeline runs, and who is on call. Agencies cost more per hour than a freelancer and less than a US in-house hire fully loaded. What you give up is control: you are buying a team's judgement, so you must trust it, and the wrong agency will happily build you nine microservices where one modular monolith would have done.
Staff augmentation. This is where most Java work should land. You have a team, an architecture, and opinions. You need two more senior Spring developers for the next six months. They join your standups, your repo, your Jira. You keep control of the design and you skip the recruiting cycle. It fits Java particularly well, because Java teams are usually building on existing platforms rather than greenfield, so the augmented engineer slots into a codebase with established conventions instead of inventing new ones.
Rates and what it really costs
These are the bands we see in our own delivery and in the deals we compete for. They move with region and seniority, so treat them as a starting frame rather than a price list.
Offshore, meaning India, Southeast Asia, and parts of Eastern Europe at the lower end, senior Java runs roughly $25 to $55 per hour. Nearshore, meaning Latin America and much of Central and Eastern Europe, runs roughly $50 to $95 per hour for people who genuinely know Spring internals and the JVM. Onshore US or UK contract Java sits around $100 to $175 per hour for senior, and higher for specialists in performance tuning or regulated finance work.
The in-house arithmetic is what surprises founders. A US senior Java salary is only the start. Benefits, payroll taxes, equipment, software licences, and the share of office and management overhead push the true annual cost well above base. Then add recruiting: either a placement fee tied to first year salary, or your own engineers' time doing screens and interviews, which is not free. Then add ramp. A senior Java developer joining a mature Spring codebase with a decade of accumulated conventions is not productive on day one. Three to eight weeks before they are net positive is realistic, longer if the build is a Maven monster with custom plugins or the domain is complicated. So the first year of an in-house Java hire is expensive in a way the offer letter does not show.
One more cost nobody prices: the bad hire. A Java developer who writes plausible-looking code but does not understand transaction boundaries or connection pooling does not fail visibly. He fails six months later during your busiest week, and the cost is the incident plus the rewrite.
How to vet a Java developer
Skip the trivia. Nobody needs to recite the contract of equals and hashCode from memory. Go after judgement.
Ask what Java version they last shipped and what they use from it. If they say 17 or 21, ask what records replaced in their code, and whether they have used virtual threads and where it did or did not help. A good answer includes a case where virtual threads were the wrong tool, because they do nothing for CPU-bound work.
Ask them to explain @Transactional to you like you are a junior. This one question sorts the room fast. A strong candidate covers: it is proxy based, so self-invocation inside the same class does not go through the proxy and the annotation silently does nothing; the default rollback is on unchecked exceptions only; propagation matters; and holding a transaction open across a network call to another service is how you exhaust a connection pool. If they just say "it makes it a transaction," keep looking.
Ask how they found the last N+1 problem they fixed. The good answer names tools: Hibernate statistics, spring.jpa.properties.hibernate.generate_statistics, the query log, or an APM showing query counts per trace. Then they name the fix: a join fetch, an entity graph, a batch size setting, or moving to a projection. If they have never met an N+1, they have not run Hibernate at load.
Ask about a production JVM incident. Not theory. What happened, what did they look at, what did they change. Listen for heap dumps and a tool to read them, GC logs, whether they know which collector they were on, thread dumps for a deadlock or thread pool starvation. Someone who says "we increased the heap and it went away" has admitted they did not find the cause.
Ask what they would not use Spring Boot for. A senior person has opinions. Maybe Quarkus or Micronaut for fast startup in a serverless context, because Spring's startup cost matters when you pay per cold start. Maybe jOOQ over JPA when the reporting queries are the whole point. Someone who believes Spring is the answer to everything has only ever had one hammer.
The take-home. Do not ask for a CRUD API. Everyone can generate that, and the AI tools generate it faster. Instead, hand them a small Spring Boot service that already exists and is subtly broken, and ask them to find and fix it in ninety minutes with a short write-up. Plant real things: a transaction that spans an external call, a lazy loading trap, an unbounded thread pool, a repository method that fetches everything into memory before filtering. What you are grading is not whether they fix all four. It is whether the write-up shows they understood the mechanism, and whether their test proves the fix. Cap it at ninety minutes and pay for it if it runs longer.
The portfolio review. If they have code to show, look at their tests before their features. Does the project use Testcontainers for real database tests, or fake everything with H2 and mocks and therefore never catch a Postgres-specific problem? Are the tests testing behaviour, or asserting that a mock was called? Look at the build file. A clean Maven POM or a Gradle build with sensible dependency management says more about discipline than any feature does.
Red flags
Everything is a microservice. A candidate who reaches for service decomposition on a three person team will hand you distributed transactions, a tracing problem, and eight deployment pipelines you do not need. Ask instead: "When would you keep this as one deployable?" A senior answer talks about team size and change coupling, not fashion.
Spring Security described as "we just permit all and handle auth in the gateway." Sometimes fine. Often it means they never learned the filter chain and cannot configure method-level security when you need it. Ask: "Walk me through how a request gets from the servlet filter chain to your controller with a JWT attached." Vagueness here is expensive later.
No answer on checked versus unchecked exceptions in a Spring service. Not because the trivia matters, but because it directly determines whether your transaction rolls back. Ask: "If this method throws IOException inside a @Transactional block, does the transaction roll back?" The correct answer is no by default, and a good candidate knows why and knows about rollbackFor.
Mocks everywhere, no integration tests. A suite that mocks the repository layer tells you nothing about whether your JPA mappings are right. Ask: "How do you test that your entity mapping actually works against the real database?" If Testcontainers or a real database in CI is not in the answer, their green build is decorative.
Cannot name what they would deprecate. Ask: "What is in your last codebase that you would rip out?" Someone who has genuinely owned Java systems has a list, and it usually includes a hand rolled thread pool, an outdated library, or a piece of config nobody understands. A candidate with no list has never been close enough to the code to have an opinion.
When to hire Java at all, and how we staff it
Be honest about whether Java is the right answer for what you are building. If you are a small team shipping a product that is mostly CRUD with a web front end, and nobody has JVM experience, Java's operational surface is a tax. Node or Python will get you further faster with the people you already have. Java earns its keep when you have real concurrency, real throughput, long-lived systems, a JVM ecosystem you already depend on, or a regulated environment where the boring stability of the platform is a feature.
Java is also the right call when you inherit it. If you bought a company or a codebase and it is Spring on Postgres with fifteen years of business logic in it, rewriting is almost always a worse bet than hiring someone who can work in it. That is a specific hire, and it is not the same person as a greenfield Spring Boot developer. Ask candidates directly whether they enjoy old code. Some genuinely do. Those people are gold and are underpriced.
Digital Heroes staffs Java as a pod rather than a body. A typical engagement puts a senior Spring engineer on feature delivery, with access to someone who does JVM and database performance when the load work arrives, and a QA person running the Testcontainers-backed integration suite so the green build means something. We work inside your repo, your conventions, your review process. If your architecture is already decided, we augment. If it is not, we will tell you where a modular monolith beats the microservices you were planning, and we will say so before you have paid us to build the wrong thing. The fastest way to start is to send us the messy part: the endpoint that times out, the migration nobody wants to touch, the service with no tests. What we find in the first week tells both of us more than any interview would.
The evidence behind this guide
Independent findings on why this investment pays off. Every link goes to the primary source.
- The average developer spends more than 17 hours a week dealing with maintenance issues such as debugging and refactoring, and about four of those hours on 'bad code' - waste that equates to nearly $85 billion annually worldwide in opportunity cost. Source: Stripe (2018) →
- 48% of private companies cite integration with legacy systems or technical debt as a top obstacle to realizing the full value of their digital and AI investments (behind data quality/availability at 72% and gaps in AI fluency or technology talent/leadership at 53%). Source: Deloitte (2026) →
- Across ten outpatient clinics the mean no-show rate was 18.8%, and the marginal cost of no-shows reached $14.58 million per year for those clinics, at roughly $196 per missed appointment (2008 figures). Source: BMC Health Services Research / PubMed Central (Kheirkhah et al.) (2015) →
- APQC's Open Standards Benchmarking data on the monthly financial close found median performers take about 6.4 calendar days to close the books, while top performers (top 25%) do it in 4.8 days or fewer and bottom performers (bottom 25%) take 10 or more days. Source: APQC (2018) →
Rohan advises mid-market and enterprise teams on ERP, CRM and custom software, and has led delivery on dozens of business-software builds.
Writes for Digital Heroes, shipping business software for 2,000+ brands across 55+ countries since 2017.