Skip to content
Houtini.

Best Local LLM for Coding, Plus the API and Image Models I Use

In today's post I'm taking a closer look at the best LLM for coding, both local and over an API. Here are the local and API models in my setup, the job each one does and the tests behind it, plus the image models I use.

Richard Baxter Richard Baxter AI Ops & Marketing Engineer
Published Updated 10 min read
On this page
  1. The best local LLM for coding on my rig
  2. What about Qwen Coder and DeepSeek Coder?
  3. The best LLM for coding over an API
  4. How the routing works
  5. Other local models I've tested for coding
  6. The best image generation model, for what I do
  7. What I haven't proven yet
The routing pipeline: Claude scopes and assembles, Kimi builds, a local Qwen coder does volume, all behind one endpoint

If you're trying to pick a model for coding, here's what runs in my own setup. The best local LLM for coding on my rig is Qwen3.6-27B, a 4-bit AWQ build that runs on one 48GB card. Over an API, DeepSeek V4 Pro does the building, and Claude does the scoping and the assembly. For images, it's Gemini's Nano Banana Pro.

That said, I think "which model" is the wrong question. What got me to a setup I trust was asking which model should do which part of the job. The answer to that isn't a model, it's a routing rule. The expensive model scopes the work and assembles the result, a cheap API model builds the modules, and a model on my own hardware does the volume work (boilerplate, tests, first-pass reviews) for the price of the electricity. Which means the expensive tokens get spent on judgement rather than typing.

Most of what follows comes from tests I've run on my own hardware and on the API models, and where a number is reported rather than measured, I say so. The hardware is two modded 48GB RTX 4090s in my office. If you've never run a local model before, start with LM Studio and come back to this afterwards.

The best local LLM for coding on my rig

Qwen3.6-27B is a dense model, where all 27 billion parameters work on every token. I run a quantised build of it. Quantised means the weights are stored at lower precision so the model fits in less memory. Mine is AWQ, a 4-bit format, and it sits on one of the two cards with a 131,072-token context (how much text it can work with at once). On 27 July I made it my everyday coding model on the rig. It's free to run and private, because nothing leaves the machine, which makes it the only tier I use for sensitive work.

There are two tests behind that choice. The first was a review-prompt experiment on about 9,000 tokens of code. My own 183-word review prompt found 4 real bugs and no false findings, while an "exhaustive expert" prompt came back with around 12 false findings. The second came a day after the switch, when I put it against Qwen3.6-35B-A3B. That's a mixture-of-experts model (MoE), where only part of the model runs for each token, so it's faster. Both wrote code that passed 12 of 12 cases. On review, the 27B gave 5 calibrated findings in 397 tokens. By calibrated I mean real issues, each given a sensible severity. The MoE kept going for around 19,000 tokens until I stopped it, and made up line references.

Day to day the 27B writes its answers at about 47 tokens per second (tok/s). With MTP switched on, which lets the model draft tokens ahead and check them, a test on 23 August with it on and off the same day gave 63.5 tok/s, although the gain moved around from one day to the next. I kept MTP off in production while I was benchmarking, though, and speed wasn't the reason. vLLM is the engine that serves the model on my cards, and on version 0.26.0 MTP can deadlock it on a long cold prefill, which means it freezes while reading a long prompt that has nothing cached yet.

Local modelWhat I use it forTokens per secondStatus
Qwen3.6-27B (AWQ, one card)The local slot: reviews, tests, boilerplate, sensitive work47 tok/s, or 63.5 with MTPDaily driver since 27 July
Qwen3.6-35B-A3B (MoE)Bounded code generation118.5 tok/s at 330WKept out of reviews
Gemma 4 31B QATGeneral; passed my 6/6 capability check40.7 tok/sWon't load at its recorded settings on vLLM 0.26.0
Gemma 4 26B-A4B (MoE)Challenger; best TypeScript of three on 2 Augustabout 150 tok/sNot promoted
fable-coder-12bSmall, quick TypeScriptabout 33 tok/sKept for small jobs
Qwen3-VL-32BReading screenshots for UI checks42-45 tok/sVision
Qwen3-Coder-Next 80B (both cards)My local coder until 26 July101.6 tok/s at 330WDemoted

Where the 27B falls short is review. On 14 August I ran three review passes over a file from one of my own projects, with a reference answer written first. Qwen made no fabrications and raised two real points Claude had missed, but it found neither of the two real bugs. So it's a first-pass reviewer, not a reviewer, and it never gets the final say on whether code goes in.

What about Qwen Coder and DeepSeek Coder?

The short answer on Qwen Coder and DeepSeek Coder is that I run neither today.

I did run a Qwen Coder model. Qwen3-Coder-Next 80B, at AWQ 8-bit and split across both cards, was my local coder until 26 July. There were two reasons I demoted it. GPU 1 sits on a PCIe x4 link, which means it gets a quarter of the lanes of a full x16 slot, and that slows down any model split across two cards. And the one-card general models reviewed code as well as it did. There's no official Coder variant in the Qwen3.6 line either, and the big one, Qwen3-Coder-480B, doesn't fit in 96GB of VRAM.

DeepSeek is a similar story. For coding, I use DeepSeek V4 over the API rather than a DeepSeek Coder model. The V4 open weights (the model files you'd download to run it yourself) are 865GB, far more than the 96GB across my two cards can hold.

Coder modelOn my rigWhy
Qwen3-Coder-Next 80BMy local coder until 26 JulySplit across both cards, it paid the PCIe x4 tax; one-card models reviewed as well
Qwen3-Coder-480BNot testedDoesn't fit in 96GB of VRAM
DeepSeek V4 (open weights)Used over the API insteadThe weights are 865GB
DeepSeek CoderNot testedV4 over the API does the job

I haven't tested DeepSeek Coder or Qwen3-Coder-480B, so I can't tell you how either would do on my work. What I can say is that a model with "Coder" in the name isn't automatically the better pick. The general Qwen3.6-27B has the job here because it fits on one card and gave the calibrated reviews in the tests above.

The best LLM for coding over an API

Over an API, DeepSeek V4 Pro is my build model. It writes the code to a spec, including the substantial modules, and it takes the long documents and the big blocks of source or text pasted into one prompt. It has that job because it codes well when the spec is self-contained, it's cheap, and it copes with a big paste. It's only ever given work that isn't sensitive.

It took that job in late July. Before then, Moonshot's Kimi models did the building, until one of them hung for more than 300 seconds on a real review of around 10,000 tokens. DeepSeek V4 returned the same request in about 80 seconds, so Kimi came out of the setup.

The evidence for DeepSeek is thinner than I'd like. DeepSeek reports 80.6% on SWE-bench Verified (a public benchmark built from real GitHub issues), and I haven't measured that myself. My own measurement is a smoke test, a 12-case parse_duration task that every model I was routing to passed at the time, plus that 80-second review.

API modelIts jobWhat I have measured
DeepSeek V4 ProBuilds code to a spec12/12 smoke test, a real review in about 80 seconds; 80.6% SWE-bench Verified is reported
DeepSeek V4 FlashBulk text, non-sensitive12/12 smoke test
GPT-6 AstraSecond-opinion code reviewThree real bugs in the houtini-lm 3.3.0 diff
ClaudeScopes, splits, assembles, verifiesNot measured; it runs the rest of this pipeline

DeepSeek V4 Flash is the bulk option, for high-volume text when the local card is busy, and again only for non-sensitive work.

For a second opinion on code I use GPT-6 Astra, through OpenAI. I had it review the 14,000-token diff for houtini-lm 3.3.0, and it found three real bugs, all fixed before the release went out.

Claude sits above all of them. It scopes, splits, assembles and verifies, because it has tools and can reason across files, and that's the part of the job where being wrong is expensive.

How the routing works

The rule is that Claude scopes, DeepSeek builds, Qwen evaluates and Claude assembles. In practice, I hand Claude a task, and it works out the shape and writes the spec. The spec goes to DeepSeek V4 Pro to build. What comes back goes to the local Qwen to review against the spec and to write the tests from it. Then Claude takes the pieces, assembles them into the codebase and checks the result with its own tools.

Two pieces of software make it work. LiteLLM is a router. It gives me one endpoint with several models behind it, and each request picks its model by an alias (a short name such as local). houtini-lm is my own MCP server. MCP is the Model Context Protocol, the way Claude talks to outside tools. houtini-lm hands bounded work to any of the models behind the router. Bounded means a job with a clear spec and a clear end. Its code_task_files tool reads files on the server side, so the source code never enters Claude's context and you don't pay tokens for it. Across the four tasks I benchmarked it on, mostly code reviews, the token saving averaged about 93%.

Router aliasModelWhere it runsIts job
localQwen3.6-27BMy rig, one cardReviews, tests, anything sensitive
deepseek-v4-proDeepSeek V4 ProDeepSeek APIBuilds to a spec
deepseek-v4-flashDeepSeek V4 FlashDeepSeek APIBulk text when the local card is busy
astraGPT-6 AstraOpenAI APISecond-opinion code review
gemma-a / gemma-bGemma 4 31BMy rig, one per cardOne generates, the other judges. Offline while the 31B won't load

The local alias is a slot, not a fixed model. It points at whichever 27B preset I have loaded. A preset is a saved set of launch settings, such as the model with or without MTP. When I load the model for Friend (my companion app, which shares the same cards), the coding slot is down. Every 27B preset serves under the same name, qwen3.6-27b, because vLLM checks that name and the router won't follow a swap on its own. houtini-lm 3.3 reads LiteLLM's /model/info to learn which real model sits behind each alias.

Scoping is the real work here. The delegated models have no tools, so they can't open a file or run a test for themselves, which means every unit of work has to be buildable from the prompt alone.

Other local models I've tested for coding

Gemma 4 31B passed my capability check on 26 July: 6 of 6 tasks, around 119 assertions, no failures, and its code review found all three defects I'd planted. It was promoted to my default that day. It no longer loads at its recorded settings on vLLM 0.26.0, though, so treat that result as history until it runs again. Its smaller sibling, Gemma 4 26B-A4B, wrote the best TypeScript of the three models I tried on 2 August and made no false findings across two review probes, but that's only three tests, so it hasn't been promoted.

Qwen3.6-35B-A3B is the fast one, at 118.5 tok/s with the cards capped at 330W. I use it for bounded code generation only. It ran away on a review in July, and although a re-test on 2 August didn't reproduce that, it stays out of reviews.

fable-coder-12b is small and quick at TypeScript. It wrote a correct, compiling MCP handler in 12.3 seconds against the 27B's 55. Qwen3-VL-32B reads images. It's the model I load for screenshot and UI checks, and I've checked that it reads the text in an image accurately.

The best image generation model, for what I do

For images I use Google's Gemini models through my Gemini MCP. Both generate_image and edit_image default to Nano Banana Pro (gemini-3-pro-image), and nothing in my Claude configs changes that, so it's what runs. Nano Banana 2 (gemini-3.1-flash-image) is the faster option for when speed matters more. I haven't measured either one against the other, or against anything else, so I can't rank them for you.

Most of what I use them for is editing rather than generating from nothing. For SimRacingCockpit, edit_image composites a product shot onto my white kitchen worktop. It works until the product has a lot of text on it, and then the text comes back garbled. On one appliance's control panel, a button label came out reading "Mutigram". On Houtini I use it for crops and annotation, and describe_image checks the results.

Fanatec Podium pedals composited onto a white kitchen worktop by Gemini edit_image
AI-generated, not a photo: Gemini, through my gemini MCP, put the Podium pedals on my worktop for a SimRacingCockpit review.

Diagrams are a different job. I draw them in code, with an SVG generator rendered to PNG, because image models are for illustration, not explanation.

Local image generation is where I have the least to show. I built a local image server with FLUX.2-klein-4B as the default and Qwen-Image-2.1 parked beside it. Qwen-Image-2.1 is non-commercial, under the Qwen Research License. The server has never been run. On 22 September I shelved it, because GPU 0 is already shared between as many models as it can handle and my power supply won't run a third card.

So if you want local image generation, I have no numbers of my own to give you, and any speeds you find for these models are published figures.

What I haven't proven yet

There are three things here I haven't proven:

  • DeepSeek's build role rests on a smoke test, an 80-second review and the vendor's reported scores. A 12-case parser doesn't go near a whole module, which is what I send it, so that part of the choice is reported, not measured.
  • The choice of Qwen over Gemma for the local slot has no scored head-to-head behind it. I have the review-prompt test and the test against the 35B MoE, but I haven't run the same tasks on both models side by side.
  • And local image generation is unmeasured on this rig, because the server has never run.

If you're starting out, you don't need the rig. Point houtini-lm at a single cheap model, a hosted one is fine, and send it the coding jobs you could describe in a sentence. Add the router when one model stops being enough.

From there, the model testing hub has the method and the live results, the benchmark runbook has the numbers for these two cards, and the inference optimisation piece covers MTP and splitting a model across cards. When you're ready to wire it up, the houtini-lm walkthrough and the vLLM setup guide cover the setup, step by step.

Continue reading.