<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vo Hoai Thuong</title>
    <description>The latest articles on DEV Community by Vo Hoai Thuong (@thuongh2).</description>
    <link>https://dev.to/thuongh2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1309106%2F683afff4-50be-4c04-8cbc-47b893c36ed9.jpeg</url>
      <title>DEV Community: Vo Hoai Thuong</title>
      <link>https://dev.to/thuongh2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thuongh2"/>
    <language>en</language>
    <item>
      <title>One API for every model, on a 2 GB VPS: meet Polyrail</title>
      <dc:creator>Vo Hoai Thuong</dc:creator>
      <pubDate>Thu, 12 Nov 2026 13:30:46 +0000</pubDate>
      <link>https://dev.to/thuongh2/one-api-for-every-model-on-a-2-gb-vps-meet-polyrail-aa6</link>
      <guid>https://dev.to/thuongh2/one-api-for-every-model-on-a-2-gb-vps-meet-polyrail-aa6</guid>
      <description>&lt;p&gt;&lt;em&gt;Polyrail is an open-source, self-hosted AI gateway. One OpenAI-compatible endpoint in front of dozens of providers, with routing, failover, budgets, teams and observability, in a single Go binary.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fynvvia1idsfjs6ug3r5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fynvvia1idsfjs6ug3r5e.png" alt="Polyrail" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you build with LLMs, you probably know this week's problem. One provider is rate-limiting you, another just raised prices, a third has a model your teammate swears by. Your code now has three SDKs, three sets of keys in three places, and no idea who spent what.&lt;/p&gt;

&lt;p&gt;Hosted routers like OpenRouter solve part of this. But sometimes you want the keys, the logs and the billing data on your own machine. That is the gap Polyrail fills.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;Polyrail sits between your apps and your model providers. Your apps talk to one endpoint. Polyrail talks to everyone else.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One API, three dialects.&lt;/strong&gt; OpenAI, Anthropic Messages and Google GenAI request formats work on the same models. Point OpenAI SDKs, Codex, OpenCode, Cline or Open WebUI at &lt;code&gt;/v1&lt;/code&gt;, Claude Code at &lt;code&gt;/anthropic&lt;/code&gt;, and Gemini CLI at &lt;code&gt;/genai&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every kind of model.&lt;/strong&gt; Chat (streaming or not), embeddings, images, text to speech, speech to text, rerank, OCR, video jobs, files and batches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Many providers.&lt;/strong&gt; OpenAI, Azure OpenAI, Anthropic, AWS Bedrock, Google Vertex AI and Gemini, Mistral, Groq, Cohere, DeepSeek, xAI, Ollama, vLLM and more, plus any OpenAI-compatible URL. The provider layer is the open-source &lt;a href="https://github.com/maximhq/bifrost" rel="noopener noreferrer"&gt;Bifrost&lt;/a&gt; core, so Polyrail does not reinvent provider adapters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A built-in catalog.&lt;/strong&gt; 265 models with prices and context lengths, generated from models.dev. Paste a provider key and its models light up.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why you would run it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Routing that survives a bad afternoon
&lt;/h3&gt;

&lt;p&gt;Give a model several targets and pick a strategy: weighted, priority, round-robin, lowest latency, lowest cost and more. If a target fails, Polyrail fails over to the next one, then to fallback models. Circuit breakers stop sending traffic to a target that keeps failing.&lt;/p&gt;

&lt;p&gt;It also speaks OpenRouter-style request routing (&lt;code&gt;models: [...]&lt;/code&gt;, &lt;code&gt;provider.order&lt;/code&gt;, &lt;code&gt;max_price&lt;/code&gt;, &lt;code&gt;:nitro&lt;/code&gt;, &lt;code&gt;:floor&lt;/code&gt;) and saved presets, so existing habits carry over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key pools that look after themselves
&lt;/h3&gt;

&lt;p&gt;Add many keys to one provider. Each key is tested, charted on its own, cooled down on rate limits, and quarantined after repeated authentication failures, with an alert when it happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsphr66n5q7shl8pdi6gk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsphr66n5q7shl8pdi6gk.png" alt="Provider keys" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Know what you spend, and cap it
&lt;/h3&gt;

&lt;p&gt;Prices are per 1M tokens, including prompt-cache read and write prices. Every response carries its cost (&lt;code&gt;usage.cost&lt;/code&gt; and an &lt;code&gt;X-GW-Cost-Micros&lt;/code&gt; header). On top of that you get prepaid org credits, per-key monthly budgets, and budgets per org, workspace, member or key. An exact response cache, a semantic cache and idempotency keys keep repeated calls cheap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safe enough for a team
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Organizations, workspaces and roles (owner, admin, member, viewer).&lt;/li&gt;
&lt;li&gt;SSO with OIDC and SAML, verified domains, SCIM provisioning.&lt;/li&gt;
&lt;li&gt;API keys stored only as hashes, rotation with a grace period, and an audit log of every admin action.&lt;/li&gt;
&lt;li&gt;Guardrails: PII and credential masking, prompt-injection detection, regex filters that redact or block.&lt;/li&gt;
&lt;li&gt;Policies for allowed models and providers, zero-data-retention requirements and data regions, refused with a clear 403 reason.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  See everything
&lt;/h3&gt;

&lt;p&gt;Usage by model, key, member and workspace, request logs, CSV export, Prometheus metrics, JSON logs, OpenTelemetry trace export, signed webhooks, and alerts to Slack, Telegram, Discord, Teams and others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpj0eg5oragonyrncm6jw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpj0eg5oragonyrncm6jw.png" alt="Model catalog" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also a console with a streaming playground and a &lt;strong&gt;Connect&lt;/strong&gt; page that hands you the exact endpoint, key and config for each tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fceay6fi5hsvzhpu66brc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fceay6fi5hsvzhpu66brc.png" alt="Connect page" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Light by design
&lt;/h2&gt;

&lt;p&gt;Polyrail ships as one Go binary with an embedded database (&lt;a href="https://github.com/cockroachdb/pebble" rel="noopener noreferrer"&gt;Pebble&lt;/a&gt;). No Python runtime, no database server to babysit.&lt;/p&gt;

&lt;p&gt;The README reports these measurements, taken on the development machine with a local mock provider, so they show gateway overhead and not model latency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Idle with the full catalog loaded: about 61 MB of memory and about 0.3% of one CPU core.&lt;/li&gt;
&lt;li&gt;5,000 chat requests at concurrency 50 on a single core: about 7,700 requests per second, p50 5.3 ms, p99 18 ms, no errors, peak 69 MB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The load generator shared the same CPU, and your numbers will differ. The method is in the repo.&lt;/p&gt;

&lt;p&gt;That is why a 1 vCPU, 2 GB VPS is a supported target. When you outgrow it, the same binary runs as stateless replicas on Postgres (config), Valkey (rate limits) and ClickHouse (analytics).&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in two minutes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run -p 8080:8080 -v polyrail:/data \
  -e &lt;span class="nv"&gt;MASTER_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$(&lt;/span&gt;openssl rand -hex 32&lt;span class="o"&gt;)&lt;/span&gt; \
  -e &lt;span class="nv"&gt;ADMIN_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;you@example.com \
  -e &lt;span class="nv"&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'choose-a-long-one'&lt;/span&gt; \
  ghcr.io/thuongh2/polyrail:edge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8080/app/&lt;/code&gt;, sign in, add a provider key under &lt;strong&gt;Admin → Providers&lt;/strong&gt;, and create an API key. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/v1/chat/completions \
  -H &lt;span class="s2"&gt;"Authorization: Bearer sk-gw-..."&lt;/span&gt; \
  -H &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; \
  -d &lt;span class="s1"&gt;'{"model": "openai/gpt-4o-mini", "messages": [{"role": "user", "content": "Hello"}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any OpenAI SDK works by changing its base URL. Back up &lt;code&gt;MASTER_KEY&lt;/code&gt;: it encrypts the provider keys stored in the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it was built
&lt;/h2&gt;

&lt;p&gt;Polyrail was built by an AI agent team working under written rules: a product owner, tech lead, developer, QA, security reviewer and an anti-slop reviewer, with tests first and verification before any claim of done. The rules and memory are in the repo (&lt;code&gt;CLAUDE.md&lt;/code&gt; and &lt;code&gt;.claude/agents/&lt;/code&gt;), so you can judge the process yourself. Every feature went through a security review, and the findings are in &lt;code&gt;docs/SECURITY.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is not
&lt;/h2&gt;

&lt;p&gt;Polyrail is not a hosted marketplace. You bring your own provider keys and run your own server. It is a young project, so expect rough edges, and read the docs before putting it in front of production traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code and docs: &lt;strong&gt;github.com/thuongh2/polyrail&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Image: &lt;code&gt;ghcr.io/thuongh2/polyrail&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;License: Apache-2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try it, open an issue with what broke or what was missing. Stars help too.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>llm</category>
      <category>linux</category>
    </item>
    <item>
      <title>Stop letting your AI agent guess how your code works</title>
      <dc:creator>Vo Hoai Thuong</dc:creator>
      <pubDate>Wed, 18 Mar 2026 12:24:41 +0000</pubDate>
      <link>https://dev.to/thuongh2/stop-letting-your-ai-agent-guess-how-your-code-works-53b6</link>
      <guid>https://dev.to/thuongh2/stop-letting-your-ai-agent-guess-how-your-code-works-53b6</guid>
      <description>&lt;p&gt;I built Mimir — a Go-based code intelligence engine that indexes your repository into a knowledge graph and exposes it to AI agents via MCP.&lt;/p&gt;

&lt;p&gt;The problem: Claude, Copilot, Cursor — they're all doing grep + vibes when navigating your codebase. They miss call chains, blast radius, and&lt;br&gt;
  module boundaries.&lt;/p&gt;

&lt;p&gt;Mimir gives them a map.&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mimir analyze . — builds a full knowledge graph in &amp;lt; 8s (1,000 files)&lt;/li&gt;
&lt;li&gt;Exposes 7 MCP tools: query(), context(), impact(), detect_changes(), rename(), cypher(), list_repos()&lt;/li&gt;
&lt;li&gt;Auto-configures Claude Code, VS Code Copilot, Cursor, Windsurf, Zed, OpenCode, and Antigravity&lt;/li&gt;
&lt;li&gt;Incremental re-index via git-diff in &amp;lt; 2s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why Go?&lt;br&gt;
The previous version (Node.js) took 45s to index and ate 800MB RAM. Mimir does the same in &amp;lt; 8s with &amp;lt; 120MB.&lt;/p&gt;

&lt;p&gt;Open source, MIT licensed.&lt;br&gt;
👉 &lt;a href="https://github.com/thuongh2/git-mimir" rel="noopener noreferrer"&gt;github.com/thuongh2/git-mimir&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
