<?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: Scalix World</title>
    <description>The latest articles on DEV Community by Scalix World (@scalixworld).</description>
    <link>https://dev.to/scalixworld</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%2F4032657%2F1b052ba3-f9f1-41ec-b6c4-ec299bd06172.png</url>
      <title>DEV Community: Scalix World</title>
      <link>https://dev.to/scalixworld</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scalixworld"/>
    <language>en</language>
    <item>
      <title>Give Claude Code a Database</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Sat, 08 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/give-claude-code-a-database-17cc</link>
      <guid>https://dev.to/scalixworld/give-claude-code-a-database-17cc</guid>
      <description>&lt;p&gt;You have Claude Code open. It has scaffolded the project, written the handlers, and the data layer is sitting there fully written against a database that does not exist yet. So you stop, open a browser tab, click through a provisioning form, copy a connection string, paste it into &lt;code&gt;.env&lt;/code&gt;, and come back.&lt;/p&gt;

&lt;p&gt;That interruption is the whole problem. Not a hard one, just a constant one, and it lands at exactly the moment you had momentum. The agent wrote every line of code that talks to Postgres. It just had no way to make Postgres exist.&lt;/p&gt;

&lt;p&gt;Here is the version where it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect once
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP&lt;/a&gt; is the open standard for handing an agent tools it can actually call. Scalix runs a hosted MCP server, so connecting is one command and one API key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http scalix https://api.scalix.world/v1/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$SCALIX_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;--scope project&lt;/code&gt; to check the connection into &lt;code&gt;.mcp.json&lt;/code&gt; and share it with your team, or &lt;code&gt;--scope user&lt;/code&gt; to have it in every project on your machine. Run &lt;code&gt;/mcp&lt;/code&gt; inside a session to confirm it connected.&lt;/p&gt;

&lt;p&gt;That is the setup. Nothing to install, nothing to run locally, and the same key that reaches the database also covers &lt;a href="https://dev.to/blog/deploy-with-claude-code"&gt;deploys&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then just ask
&lt;/h2&gt;

&lt;p&gt;With the tools connected, the database becomes something you describe rather than something you go and do:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a Postgres database for this app, put the connection string in &lt;code&gt;.env&lt;/code&gt; as &lt;code&gt;DATABASE_URL&lt;/code&gt;, then write and run the initial schema migration for users and sessions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent works through that in order. It creates the database, reads back the connection string, writes it into your &lt;code&gt;.env&lt;/code&gt;, generates the migration, applies it, and queries the result to confirm the tables landed.&lt;/p&gt;

&lt;p&gt;What comes back is an ordinary DSN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres://&amp;lt;user&amp;gt;@&amp;lt;host&amp;gt;:5432/&amp;lt;database&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing exotic. It goes in &lt;code&gt;.env&lt;/code&gt; like any other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres://&amp;lt;user&amp;gt;@&amp;lt;host&amp;gt;:5432/&amp;lt;database&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can pick the major version when it is created. PostgreSQL 16, 17, and 18 are available, and 16 is the default if you do not say. That choice is fixed for the life of the database, so branches and point in time restores stay on the same major rather than quietly drifting underneath you.&lt;/p&gt;

&lt;p&gt;Then the agent writes the schema, which is the part it was always good at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;timestamptz&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;sessions&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;expires_at&lt;/span&gt; &lt;span class="n"&gt;timestamptz&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It applies that through the migration tool and then verifies with a query, reading the result back into the conversation. If the migration fails, it sees the error itself and fixes it. That read-back is the difference between an agent that runs commands and an agent that finishes the job.&lt;/p&gt;

&lt;p&gt;Worth being clear about what you are connecting to. ScalixNova is a purpose-built storage engine that speaks the Postgres wire protocol, not a managed wrapper around upstream Postgres. We wrote the engine, which is a deliberate choice we explain in &lt;a href="https://dev.to/blog/built-not-assembled"&gt;built, not assembled&lt;/a&gt;. From your side of the socket it does not change your habits: &lt;code&gt;psql&lt;/code&gt; connects, your ORM connects, your migration tool connects, all over TLS, all speaking the protocol they already speak. And if you want to know what happens to your data after a write is confirmed, &lt;a href="https://dev.to/blog/how-durability-works-scalixnova"&gt;how durability works in ScalixNova&lt;/a&gt; walks through it layer by layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branch it before you break it
&lt;/h2&gt;

&lt;p&gt;The prompt nobody types confidently is the destructive one. Dropping a column, rewriting a table, backfilling three million rows. You want the agent to try it, and you do not want it tried against the database your app is using.&lt;/p&gt;

&lt;p&gt;So give it somewhere else to try:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a branch database, run the column rename and backfill against it, check the row counts, then tell me what happened before we touch the real one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent creates an isolated branch database with its own scoped token, does the work there, reports back, and drops the branch when it is done. Branches also carry a TTL, so a scratch database the agent forgot about expires on its own instead of accumulating.&lt;/p&gt;

&lt;p&gt;The useful shift here is psychological more than technical. When trying a bad migration costs one tool call and no risk, you let the agent attempt the awkward one instead of talking yourself into the safe half measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scale to zero and side projects
&lt;/h2&gt;

&lt;p&gt;Agent-created databases multiply. You build a weekend thing, it needs Postgres, the agent makes one, and three weeks later you have forgotten it exists. On most platforms that forgotten database is a line item that shows up every month whether or not anything ever connects to it.&lt;/p&gt;

&lt;p&gt;On Scalix a paused database does not bill compute. Nothing is running, so nothing is metered for running. That is not a special tier we bolted onto the database product; scale to zero works the same way across the platform because the same lifecycle layer manages everything on it.&lt;/p&gt;

&lt;p&gt;Practically, this is what makes the loop in this post safe to actually use. You can let the agent create a database per experiment without keeping a mental ledger of what you owe for abandoned ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stays human
&lt;/h2&gt;

&lt;p&gt;Handing an agent database tools does not mean handing it everything, and the boundary should be explicit rather than vibes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scopes are the real control.&lt;/strong&gt; Scalix API keys carry separate scopes for querying, branching, and admin operations. A key that can run migrations is a different key from one that can only read. Give the agent the narrowest scope that does the job, and keep production admin on a key that lives somewhere the agent cannot reach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Destructive SQL asks first.&lt;/strong&gt; Statements like &lt;code&gt;DROP&lt;/code&gt;, &lt;code&gt;TRUNCATE&lt;/code&gt;, and bulk &lt;code&gt;DELETE&lt;/code&gt; through the query tool return a confirmation requirement rather than executing, and the call has to be repeated with a confirmation token. It is a speed bump on purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production data access is a policy decision, not a prompt.&lt;/strong&gt; Whether an agent should read real customer rows at all is a question about your obligations to the people in those rows. Decide it deliberately, write it down, and let branches carry the experimental work.&lt;/p&gt;

&lt;p&gt;None of that is friction for its own sake. It is the difference between an agent that can operate your database and an agent that can operate your database at 2am on a Friday.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The gap was never that Claude Code could not handle databases. It writes better SQL than most of us. The gap was that it had no way to make one exist, so you kept leaving the session at the same point in every project.&lt;/p&gt;

&lt;p&gt;Connect the tools once and that step disappears. Describe the database you want, get a DSN back, keep going.&lt;/p&gt;

&lt;p&gt;You can start on &lt;a href="https://scalix.world/nova?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Nova&lt;/a&gt;; current terms are on the &lt;a href="https://scalix.world/pricing?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;. Point your agent at the MCP server, ask it for a database, and see how far the session gets before you need another window. If you build something with it, tell us on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://x.com/scalix_world" rel="noopener noreferrer"&gt;X&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>database</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Serverless Postgres in 2026: Neon, Supabase, and the tradeoffs</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/serverless-postgres-in-2026-neon-supabase-and-the-tradeoffs-1i9b</link>
      <guid>https://dev.to/scalixworld/serverless-postgres-in-2026-neon-supabase-and-the-tradeoffs-1i9b</guid>
      <description>&lt;p&gt;Three products describe themselves as serverless Postgres and mean three different things by it. Neon means separated storage and compute with branching as the headline. Supabase means a whole backend that happens to be built on Postgres. ScalixNova, which is ours, means an engine we wrote from scratch that speaks the Postgres wire protocol.&lt;/p&gt;

&lt;p&gt;Feature grids do not help much here, because the three are not competing on the same axis. What follows is what each actually does, taken from their own documentation and cited inline, and where the tradeoffs land.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the label is supposed to mean
&lt;/h2&gt;

&lt;p&gt;Strip the marketing and "serverless Postgres" is usually claiming three things.&lt;/p&gt;

&lt;p&gt;Storage and compute are separated, so the component holding your data is not the component running queries. Idle databases suspend, so you are not paying for a server nobody is talking to. And billing follows usage instead of a provisioned box.&lt;/p&gt;

&lt;p&gt;All three do some version of that. Everything built around it is where they part company.&lt;/p&gt;

&lt;h2&gt;
  
  
  Neon: branching as the organising idea
&lt;/h2&gt;

&lt;p&gt;Neon's &lt;a href="https://neon.com/docs/introduction/branching" rel="noopener noreferrer"&gt;branching docs&lt;/a&gt; are unambiguous about the mechanism. "A branch is a copy-on-write clone of your data." Creating one copies nothing. A branch and its parent "share the same data but diverge at the point of branch creation", writes to the branch "are saved as a delta", and creating one "does not increase load on the parent branch or affect it in any way".&lt;/p&gt;

&lt;p&gt;That is the strongest branching mechanism of the three, and it is worth saying plainly rather than burying: ours works differently and is slower at the same job. More on that below.&lt;/p&gt;

&lt;p&gt;What bounds Neon's branching is the history window. Retention defaults to six hours on their entry plan and one day on paid plans, configurable up to seven days on Launch and thirty on Scale, with the tradeoff stated in &lt;a href="https://neon.com/docs/introduction/point-in-time-restore" rel="noopener noreferrer"&gt;their own docs&lt;/a&gt;: "Increasing the history window expands recovery options but also increases storage costs." Branch expiry for temporary environments and schema-only branching for sensitive data are both documented features.&lt;/p&gt;

&lt;p&gt;On coverage, Neon lists eight active AWS regions in &lt;a href="https://neon.com/docs/introduction/regions" rel="noopener noreferrer"&gt;their region docs&lt;/a&gt;: N. Virginia, Ohio, Oregon, Frankfurt, London, Singapore, Sydney and São Paulo. The Azure regions are marked deprecated and no longer accept new projects. A project's region is fixed at creation, and their guidance if you picked wrong is blunt: "If you need your data in a different region, you create a new Neon project in that region and migrate your database there."&lt;/p&gt;

&lt;p&gt;The ownership question is worth naming because people ask. Databricks &lt;a href="https://neon.com/blog/neon-and-databricks" rel="noopener noreferrer"&gt;announced its acquisition of Neon&lt;/a&gt; on 14 May 2025, and the founders wrote that "Neon isn't going anywhere, we're doubling down". Whether that reassures you depends entirely on how you feel about a database roadmap living inside a large data platform vendor. It is a fact to weigh, not a criticism.&lt;/p&gt;

&lt;p&gt;Neon is deliberately database-only. Compute, object storage, auth and inference come from elsewhere in your stack, and that is the design rather than an omission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supabase: the database as a backend
&lt;/h2&gt;

&lt;p&gt;Supabase is a different category wearing an overlapping label. The database is standard Postgres. The product is everything wrapped around it.&lt;/p&gt;

&lt;p&gt;PostgREST generates a REST API directly from your schema. Supabase &lt;a href="https://supabase.com/docs/guides/api" rel="noopener noreferrer"&gt;describe it&lt;/a&gt; as "a thin API layer on top of Postgres" whose interface is "automatically reflected from your database's schema", covering CRUD, views, materialized views, foreign tables, functions and computed columns, with every request resolving "to a single SQL statement leading to fast response times and high throughput". Security runs through Postgres itself: the API is "configured to work with Postgres's Row Level Security, provisioned behind an API gateway with key-auth enabled". &lt;code&gt;pg_graphql&lt;/code&gt;, listed in their own architecture README, adds a GraphQL API as a Postgres extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://supabase.com/docs/guides/realtime" rel="noopener noreferrer"&gt;Realtime&lt;/a&gt; ships three distinct capabilities: Broadcast to "send low-latency messages between clients", Presence to "track and synchronize user state across clients", and Postgres Changes to "listen to database changes in real-time".&lt;/p&gt;

&lt;p&gt;And the stack is open source under Apache-2.0. The &lt;a href="https://github.com/supabase/supabase" rel="noopener noreferrer"&gt;README&lt;/a&gt; lists the components: Postgres, Realtime, PostgREST, GoTrue, Storage, pg_graphql, postgres-meta and Envoy. Self-hosting is documented via Docker Compose, with community Helm charts and Traefik setups alongside it.&lt;/p&gt;

&lt;p&gt;Those three things, the open core, realtime, and APIs generated from your schema, are genuine strengths, and we have none of them. If any one is load bearing in your architecture, this survey is short: Supabase is your answer and nothing below changes that.&lt;/p&gt;

&lt;p&gt;The honest asterisk is on self-hosting, and Supabase state it themselves. A &lt;a href="https://supabase.com/docs/guides/self-hosting" rel="noopener noreferrer"&gt;self-hosted deployment&lt;/a&gt; "runs as a single project which means that Studio doesn't support multiple organizations or projects", and branching, managed backups and PITR, advanced metrics, analytics and vector buckets, ETL and the platform management API are all listed as unavailable. Self-hosted is community supported. Provisioning, hardening, Postgres maintenance, high availability, backups and monitoring become yours. Open source removes vendor dependency. It does not remove the operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  ScalixNova: what changes when you write the engine
&lt;/h2&gt;

&lt;p&gt;Ours is the odd one out here, so the same treatment, gaps first where they matter.&lt;/p&gt;

&lt;p&gt;ScalixNova is not managed upstream Postgres and it is not a fork. It is a purpose-built storage engine that speaks the PostgreSQL wire protocol. Storage and compute are separate components we wrote: a storage engine that materialises pages from the write ahead log, a WAL keeper providing term-fenced durable WAL storage, and a compute layer running PostgreSQL workers on the major you chose. It is designed from day one for Paxos-style quorum replication as we grow beyond one region, rather than replication bolted on afterwards. The durability half of that is worked through in &lt;a href="https://dev.to/blog/how-durability-works-scalixnova"&gt;how durability works in ScalixNova&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From your side of the socket, none of that is visible. A standard DSN, TLS required, &lt;code&gt;psql&lt;/code&gt; and your ORM and your migration tool connect the way they always have.&lt;/p&gt;

&lt;p&gt;You pick PostgreSQL 16, 17 or 18 at creation, and the major is fixed for the life of that database, inherited by every branch and every point in time restore. That pinning falls out of the architecture rather than being a limitation we chose to live with, and the reasoning is in &lt;a href="https://dev.to/blog/postgres-16-17-18-serverless"&gt;Postgres 16, 17 and 18 on a serverless engine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Branching is where writing your own engine currently costs us. A Scalix branch is restore-based: built from the parent's backup to a chosen point in time, fully isolated, with its own scoped token and a TTL so scratch branches expire instead of accumulating. It carries real data, and it does the job well for handing an AI agent a database it is allowed to break, particularly over &lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP&lt;/a&gt;. It is not a copy-on-write clone and we do not describe it as one. For large databases branched frequently, Neon's mechanism is faster, and that gap is not closing this month.&lt;/p&gt;

&lt;p&gt;Point in time recovery runs on the same machinery, bounded to five minutes while the database is active, with the open WAL segment shipped when it suspends. Compute is acquired per connection and released after, so a paused database does not meter compute.&lt;/p&gt;

&lt;p&gt;Coverage is one region, in the EU, on dedicated hardware we operate, with India next. That is one against Neon's eight and Supabase's many.&lt;/p&gt;

&lt;p&gt;What the from-scratch route buys is control of the paths that matter when something goes wrong: which binaries replay your WAL, what a restore does when you ask for a moment outside your retention window, how a branch is isolated from its parent. What it costs is that a two-person team carries correctness that upstream Postgres carries for everyone else, and that is a concentration risk you should price in rather than take on faith.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four questions that actually decide it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How often do you branch, and how large is the database?&lt;/strong&gt; If branching per pull request on a large database is the workflow, the mechanism matters more than anything else on this page, and Neon's is the better one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much of the backend do you want from one vendor?&lt;/strong&gt; Supabase gives you auth, storage, functions and realtime as a suite. Neon gives you a very good database and expects you to compose the rest. Scalix puts the database inside a platform where containers, functions, object storage, auth and inference sit behind the same key and the same usage ledger. These are three different answers to how many vendors you want to hold, not three quality levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does it run, and who operates it?&lt;/strong&gt; Neon on AWS. Supabase hosted on major public cloud, or on your own Docker host if you self-host. Scalix on dedicated European hardware operated by European and Indian companies with no US parent. If data residency or operator sovereignty is driving the decision, that difference is the point. If region count is driving it, we lose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who owns the roadmap?&lt;/strong&gt; Neon sits inside Databricks. Supabase's core is Apache-2.0, so the worst case is that you run it yourself. Scalix is founder owned with a closed core, which means the incentives are ours and also that you could not fork us if we disappeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting out, which is worth checking before you get in
&lt;/h2&gt;

&lt;p&gt;All three speak the standard Postgres wire protocol, so the database move is ordinary tooling: &lt;code&gt;pg_dump&lt;/code&gt; and &lt;code&gt;pg_restore&lt;/code&gt; over a TLS DSN, or logical replication for a shorter cutover. No proprietary format exists on any side of that.&lt;/p&gt;

&lt;p&gt;The parts that do not move cleanly are the parts that are not Postgres. Supabase auth users and storage objects are application level migrations. Neon branch history does not transfer as branch history. Scalix branch and PITR windows stay behind. Plan for the database to be straightforward and the surrounding features to be work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each is the right answer
&lt;/h2&gt;

&lt;p&gt;Neon, if branching is the workflow rather than a feature you use twice a year, if you want a database-only vendor, or if you need a region we do not have.&lt;/p&gt;

&lt;p&gt;Supabase, if realtime subscriptions or schema-generated APIs are load bearing, if an open core you can read and self-host is a requirement, or if you want the whole backend from one place with years of production history behind it.&lt;/p&gt;

&lt;p&gt;ScalixNova, if you want serverless Postgres with the rest of the stack on the same key and the same bill, if EU operation and residency drive the decision, or if you want Postgres 18 today with the major pinned for the life of the database. Not if you need more than one region this quarter, and not if the branching mechanism is the deciding feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try them against your own workload
&lt;/h2&gt;

&lt;p&gt;The fastest way to settle any of this is to create a database on two of them and run your own migration and your own query pattern. Branch mechanics, restore behaviour and idle wake time are all things you can measure in an afternoon, and the measurement will beat anybody's comparison table, including this one.&lt;/p&gt;

&lt;p&gt;If you want to test the from-scratch engine, you can create a database on 16, 17 or 18 at &lt;a href="https://scalix.world/nova?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Nova&lt;/a&gt; without a card, on a one time trial credit, and the rates are on the &lt;a href="https://scalix.world/pricing?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;. If one of the others turns out to fit your workload better, that is a good outcome and we would rather you found out early. Come argue with any of the above on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>App hosting in 2026: Fly, Render, Railway and microVMs</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/app-hosting-in-2026-fly-render-railway-and-microvms-20ha</link>
      <guid>https://dev.to/scalixworld/app-hosting-in-2026-fly-render-railway-and-microvms-20ha</guid>
      <description>&lt;p&gt;App hosting stopped being one category some time in the last two years. The four platforms below all answer "where should this process run", and they answer it with different units, different billing shapes, and different opinions about what happens when nobody is calling your app.&lt;/p&gt;

&lt;p&gt;One of the four is ours, which is disclosed rather than hidden, and it goes first because it is the proposition the other three are a useful check against. Every competitor number here comes from that vendor's own pricing or documentation, cited inline and checked on 6 August 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you are actually choosing between
&lt;/h2&gt;

&lt;p&gt;Five axes do most of the work, and they are not the ones the landing pages lead with.&lt;/p&gt;

&lt;p&gt;The pricing shape: flat monthly instance, metered usage, or preset VM. What happens on idle, which is where the surprises live. The isolation boundary, and whether the vendor publishes one. Region coverage. And how much of the rest of your stack comes from the same bill.&lt;/p&gt;

&lt;p&gt;That last axis is the one we built for, so start there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scalix Run
&lt;/h2&gt;

&lt;p&gt;Scalix Run deploys containers on microVMs. Each deployment gets its own kernel rather than sharing one with other tenants, and that is the default rather than a premium tier. Firecracker boot measures about 76 ms on our hardware, VMM to userspace. That figure is the boot of the microVM in isolation. It is not a create-to-ready time and it is not a function cold start, both of which are longer numbers, and it would be dishonest to present it as either.&lt;/p&gt;

&lt;p&gt;You deploy from a source directory with the runtime detected from &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt; or &lt;code&gt;Cargo.toml&lt;/code&gt;, from your own Dockerfile, or from a prebuilt image. Every deploy is an immutable revision. Health checks gate the cutover, so a build that fails to come up never takes traffic. Rollback to any previous revision is one command. The service URL does not change between deploys.&lt;/p&gt;

&lt;p&gt;Sizing runs from half a vCPU with 256 MB up to 4 vCPU with 8 GB, a lower ceiling than any of the other three. Metering is per vCPU and per GiB, billed per second while a service is awake, with concurrency-based autoscaling and a minimum instance count you can set to zero; the rates are on the &lt;a href="https://scalix.world/pricing?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;. Set that floor to zero and, when nothing is calling the service, no compute meters.&lt;/p&gt;

&lt;p&gt;Note the shape of that meter, because it decides whether our rate is comparable to anyone else's. It prices allocated capacity while the service is awake, not measured consumption. Against a purely consumption-metered vendor, a spiky workload may well cost less there and a steady one less here. Model your own traffic rather than either headline number.&lt;/p&gt;

&lt;h3&gt;
  
  
  What sits on the same key
&lt;/h3&gt;

&lt;p&gt;The per-deployment kernel is the part people ask about first, but it is not the argument. The argument is that the service is not on its own.&lt;/p&gt;

&lt;p&gt;A Scalix Run service sits beside managed Postgres on 16, 17 or 18 with branching and point in time recovery, object storage, serverless functions, app auth, DNS and first party inference. One credential authorises all of it, and one usage ledger meters all of it, because it was written as a single system rather than assembled from parts that later had to agree with each other. That is worked through in &lt;a href="https://dev.to/blog/one-key-one-bill"&gt;one key, one bill&lt;/a&gt; and &lt;a href="https://dev.to/blog/built-not-assembled"&gt;built, not assembled&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In practice that means the thing you deploy, the database it queries, the bucket it writes to and the model call it makes are one integration rather than four, and they reconcile against each other on one bill. Long-running services also make Run a reasonable place to host an &lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP server&lt;/a&gt; or an &lt;a href="https://dev.to/blog/deploy-ai-agent-cloud"&gt;agent loop&lt;/a&gt;, which are the same shape as any other always-on process, and the control plane is operable by an agent as well as by a human.&lt;/p&gt;

&lt;h3&gt;
  
  
  The limits, plainly
&lt;/h3&gt;

&lt;p&gt;One region, in the EU, with India next. That is the fewest of the four and the first thing to check against your latency requirements.&lt;/p&gt;

&lt;p&gt;No managed Redis, Kafka or CDN. A 4 vCPU ceiling on a single service, which is lower than the other three and rules out the largest single-box workloads.&lt;/p&gt;

&lt;p&gt;We publish uptime at &lt;a href="https://status.scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;status.scalix.world&lt;/a&gt; and support is direct access to the people who wrote the platform. We do not sell support tiers or availability commitments, and if procurement requires one on paper, that gap is real and the other three have an answer we do not.&lt;/p&gt;

&lt;p&gt;Two engineers built and operate this. That is why it is one system, and it is also a concentration risk you should price into the decision rather than take on faith.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fly.io
&lt;/h2&gt;

&lt;p&gt;Fly optimises for direct control of the machine. Their unit is the Machine, a VM whose lifecycle, resources and region placement you drive yourself through a REST API or &lt;code&gt;flyctl&lt;/code&gt;, and Fly's &lt;a href="https://fly.io/blog/design-and-implementation/" rel="noopener noreferrer"&gt;engineering writing&lt;/a&gt; has described the underlying thing as approximately OCI containers repackaged as KVM microVMs, which is a more useful description than either "container" or "VM" alone.&lt;/p&gt;

&lt;p&gt;The headline strength is reach plus a mature first party database. &lt;a href="https://fly.io/docs/mpg/" rel="noopener noreferrer"&gt;Fly Managed Postgres&lt;/a&gt; is documented in twelve regions on Postgres 16, with high availability, backups and connection pooling on every plan. Their docs also list what is not there yet, including version upgrades and migration tooling, which is a good habit more vendors should copy.&lt;/p&gt;

&lt;p&gt;Billing shape: preset CPU and RAM sizes billed by the hour. Stopping a Machine is the honest version of scale to zero, in that compute stops and storage does not: &lt;a href="https://fly.io/docs/about/pricing/" rel="noopener noreferrer"&gt;their pricing docs&lt;/a&gt; state plainly that a stopped Machine keeps billing for its root filesystem storage. Object storage and Redis on Fly are operated by third parties rather than by Fly, which gets you to specialist products quickly and leaves you carrying the seams between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Render
&lt;/h2&gt;

&lt;p&gt;Render optimises for predictability. You buy a sized instance at a flat monthly price, &lt;a href="https://render.com/pricing" rel="noopener noreferrer"&gt;billed&lt;/a&gt; "prorated by the second", and it runs. Nothing about the bill is a surprise, which is the entire pitch and a good one.&lt;/p&gt;

&lt;p&gt;The headline strength is the depth of the managed data services. &lt;a href="https://render.com/docs/postgresql" rel="noopener noreferrer"&gt;Render Postgres&lt;/a&gt; is first party with point in time recovery on paid tiers and high availability from Pro upward, there is a Redis-compatible key value service beside it, and around those sit static sites on a CDN, cron jobs, preview environments and infrastructure as code without you assembling any of it.&lt;/p&gt;

&lt;p&gt;Billing shape runs opposite to the rest of this list, so read it carefully. Paid instance types do not spin down at all, which means a service that receives no traffic for a week still bills its full monthly rate. Only the &lt;a href="https://render.com/docs/free" rel="noopener noreferrer"&gt;entry instance type&lt;/a&gt; spins down, after "15 minutes without receiving any inbound traffic", and waking "takes about one minute". Five &lt;a href="https://render.com/docs/regions" rel="noopener noreferrer"&gt;regions&lt;/a&gt;: Oregon, Ohio, Virginia, Frankfurt and Singapore, fixed once a service is created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Railway
&lt;/h2&gt;

&lt;p&gt;Railway optimises for usage-shaped bills on hardware it owns, which makes it the only one of the four besides us not renting from a hyperscaler. Railway Metal is described in &lt;a href="https://docs.railway.com/reference/regions" rel="noopener noreferrer"&gt;their docs&lt;/a&gt; as "hardware that we own and operate in datacenters around the world", and on whether they will stay on a public cloud the answer is direct: "No. We are migrating completely onto Railway managed hardware." Four regions carry the Metal name: California, Virginia, Amsterdam and Singapore.&lt;/p&gt;

&lt;p&gt;Billing shape: per second consumption drawn against monthly plan credits, at &lt;a href="https://docs.railway.com/reference/pricing" rel="noopener noreferrer"&gt;published per second rates&lt;/a&gt; for vCPU and memory.&lt;/p&gt;

&lt;p&gt;Idle handling is a feature called &lt;a href="https://docs.railway.com/reference/app-sleeping" rel="noopener noreferrer"&gt;Serverless&lt;/a&gt;, and its mechanism is unusual enough that you should check it against your own app rather than assume. Railway watches outbound packets, not inbound: "Inbound traffic is excluded from considering when to sleep a service." An open database connection pool, framework telemetry or an NTP client is enough to keep a service awake indefinitely. Their docs also warn that the first request after sleep "may return a 502 Bad Gateway response".&lt;/p&gt;

&lt;p&gt;One thing to know before assuming a managed database: Railway's Postgres templates are, in &lt;a href="https://docs.railway.com/reference/databases" rel="noopener noreferrer"&gt;their own words&lt;/a&gt;, "considered unmanaged, meaning you have total control over their configuration and maintenance". Backups are yours to arrange. That is more control and more work, and which you want is a genuine preference rather than a defect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolation, honestly
&lt;/h2&gt;

&lt;p&gt;Fly and Scalix both publish microVM models, so on that axis the two of us are close and neither should be selling it as a differentiator against the other.&lt;/p&gt;

&lt;p&gt;Render and Railway describe services and containers in the documentation we read, and we found no published statement either way on the kernel boundary between tenants. Absence of a published claim is not evidence of a weaker one, and inferring an isolation property from a marketing page is a bad habit. If a specific boundary matters to you, ask each vendor directly and get the answer in writing.&lt;/p&gt;

&lt;p&gt;The neutral version of the argument: shared-kernel containers are good isolation and hold up for the overwhelming majority of workloads. A per-workload kernel matters most when the code being executed was decided at runtime rather than at review time, which is why it comes up far more often now that agents run generated code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idle behaviour, side by side
&lt;/h2&gt;

&lt;p&gt;This is the axis that produces the most surprise bills, and all four differ.&lt;/p&gt;

&lt;p&gt;Scalix Run: minimum instances can be set to zero, and compute meters only while an instance is running. Anything you keep, such as stored data and object storage, keeps billing whether the service is awake or not.&lt;/p&gt;

&lt;p&gt;Fly: stop a Machine and compute stops at subsecond speeds, but the root filesystem keeps billing while stopped.&lt;/p&gt;

&lt;p&gt;Render: paid instance types run continuously and bill their monthly rate regardless of traffic. Only the entry type spins down, after 15 minutes without inbound traffic, waking in about a minute.&lt;/p&gt;

&lt;p&gt;Railway: Serverless sleeps a service after 10 minutes with no outbound packets, and a connection pool or telemetry defeats it. The first request after sleep may return a 502.&lt;/p&gt;

&lt;p&gt;None of these is wrong. They are four different bets about whether predictability or elasticity is the thing you are buying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each fits
&lt;/h2&gt;

&lt;p&gt;Scalix Run, if you want a per-deployment microVM kernel and scale to zero on the same key as a managed Postgres, object storage, functions and inference, and if EU operation matters to the decision. Not if you need more than one region this quarter, a support contract on paper, or more than 4 vCPU in a single service.&lt;/p&gt;

&lt;p&gt;Fly, if you want direct lifecycle control over VMs, a first party managed Postgres in the same region as your app, or the widest region coverage of the four.&lt;/p&gt;

&lt;p&gt;Render, if you want a flat monthly bill you can forecast and the deepest managed data services of the four, with preview environments and infrastructure as code included rather than assembled.&lt;/p&gt;

&lt;p&gt;Railway, if you want usage-shaped bills and a project graph where the database is a service you fully control. Not if you want a managed database, because their own docs tell you it is unmanaged.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test that settles it
&lt;/h2&gt;

&lt;p&gt;Deploy the same app twice. Watch what the bill does over a week of your actual traffic rather than a synthetic benchmark, and time the wake path after an idle period. Both are afternoon experiments, and both beat any comparison table, this one included.&lt;/p&gt;

&lt;p&gt;If you want to run that experiment against microVMs with scale to zero, &lt;a href="https://scalix.world/run?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; takes a source directory or an image, the rates are on the &lt;a href="https://scalix.world/pricing?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;, and the database that sits beside it is &lt;a href="https://scalix.world/nova?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Nova&lt;/a&gt;. If one of the other three fits your workload better, that is a good outcome and we would rather you found out in week one. Tell us what you measured on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>cloud</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>How to Deploy an AI Agent to the Cloud</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Thu, 06 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/how-to-deploy-an-ai-agent-to-the-cloud-2g5d</link>
      <guid>https://dev.to/scalixworld/how-to-deploy-an-ai-agent-to-the-cloud-2g5d</guid>
      <description>&lt;p&gt;You built an agent. It is a loop: call a model, read the tool calls it comes back with, run them, feed the results in, go again until the work is done. It runs on your laptop, it works, and it stops the moment you close the lid.&lt;/p&gt;

&lt;p&gt;Getting it running around the clock is a different problem from getting it working. Not a harder one, but a different one, and most of the guides on deploying an AI agent skip straight to the deploy command without saying what an agent actually needs from the infrastructure underneath it. That part is worth ten minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an agent needs that an app does not
&lt;/h2&gt;

&lt;p&gt;Start with the shape of the thing. A web app receives a request, does some work, returns a response, and forgets everything. An agent is the opposite: it is a process that stays alive, accumulates context, and decides for itself what to do next. Four consequences fall out of that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State has to outlive the process.&lt;/strong&gt; Conversation history, task progress, what the agent has already tried. If that lives in a Python dict, the next restart is an amnesiac. Put it in a database from the start, keyed by session or task, and write to it at the end of every loop iteration rather than at the end of the run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secrets have to come from the environment.&lt;/strong&gt; Your model provider key, your database URL, whatever credentials the tools need. These belong in environment variables set at deploy time, not baked into the image and definitely not in the repository. Rotating a key should be a redeploy, not a rebuild.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restarts are normal, so make them boring.&lt;/strong&gt; Processes get killed. A node reboots, a deploy rolls, the agent hits an unhandled exception on a malformed tool response at 3am. If your loop resumes from durable state, a restart costs you seconds. If it does not, it costs you the run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Egress and logs are the whole observability story.&lt;/strong&gt; An agent talks to an LLM API and to whatever tools you gave it, so it needs outbound network. And because you cannot attach a debugger to something that only misbehaves once a day, structured logs on every iteration (which tool, which arguments, what came back) are how you find out what your agent actually did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why functions are the wrong default here
&lt;/h2&gt;

&lt;p&gt;The instinct is to reach for serverless functions, because agents feel event-driven. It fights the model more than it helps.&lt;/p&gt;

&lt;p&gt;Functions are built for request-and-forget work inside a bounded execution window. An agent loop holds context across many model calls, keeps connections open, and can legitimately run for minutes. You end up either fighting the timeout or shredding the loop into a state machine across a dozen invocations, which is a lot of engineering to make the wrong shape fit.&lt;/p&gt;

&lt;p&gt;Functions are still useful here. They are a good home for the individual tools your agent calls, where request-and-forget is exactly right. The loop itself wants a long-running service.&lt;/p&gt;

&lt;h2&gt;
  
  
  The isolation question, honestly
&lt;/h2&gt;

&lt;p&gt;Here is the part that matters more for agents than for ordinary services.&lt;/p&gt;

&lt;p&gt;Your agent executes what a model told it to execute. Maybe it shells out. Maybe it runs generated code. Maybe it just fetches a web page, and that page contains text engineered to steer the next tool call. The blast radius of agent code is decided at runtime, not at review time, which is not true of the CRUD service running next to it.&lt;/p&gt;

&lt;p&gt;Most container platforms run your workload as a process in a shared kernel, isolated by namespaces and cgroups. That is genuinely good isolation and it holds up for the overwhelming majority of workloads. It is also, by construction, one kernel vulnerability away from your neighbours. That is a well-understood trade-off and plenty of people accept it knowingly.&lt;/p&gt;

&lt;p&gt;We think agent code is the workload where you should think twice before accepting it by default. So on Scalix Run, every deployment gets its own microVM: its own kernel, its own memory boundary, hardware-level isolation. The obvious objection is startup cost, and it used to be a real one. MicroVMs boot in roughly 76ms on our hardware, which is why this is the default tier rather than a premium one. You are not choosing between fast and isolated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packaging the loop
&lt;/h2&gt;

&lt;p&gt;Nothing exotic. Your agent needs to be a process that starts, runs, and does not exit.&lt;/p&gt;

&lt;p&gt;If it exposes an HTTP endpoint, so you can trigger it or check on it, listen on a port and read that port from the environment. If it is a pure worker driven by a queue or a timer, it just needs a main loop that blocks. Either way: no local state that matters, no secrets in the image, and logs to stdout.&lt;/p&gt;

&lt;p&gt;You do not have to write a Dockerfile if you do not want one. Scalix Run deploys from source and detects the runtime from your &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt;, or a &lt;code&gt;Dockerfile&lt;/code&gt; if you have written one, and builds the image for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying it
&lt;/h2&gt;

&lt;p&gt;With a prebuilt image, the deploy is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scalix-cloud run deploy &lt;span class="nt"&gt;--name&lt;/span&gt; agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; api.scalix.world/&amp;lt;project-id&amp;gt;/agent:v1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-instances&lt;/span&gt; 1 &lt;span class="nt"&gt;--max-instances&lt;/span&gt; 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secrets go in as environment variables on the service. Through the API that is the &lt;code&gt;env&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://api.scalix.world/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/services&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;-H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Authorization: Bearer $SCALIX_API_KEY"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api.scalix.world/&amp;lt;project-id&amp;gt;/agent:v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MODEL_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres://..."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scaling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"min_instances"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max_instances"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service comes up at a URL that does not change between deploys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://agent.run.scalix.world

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every deploy is a revision, so when a prompt change makes your agent worse in a way the tests did not catch, &lt;code&gt;scalix-cloud run rollback &amp;lt;service-id&amp;gt;&lt;/code&gt; puts the old one back. Logs come back with &lt;code&gt;scalix-cloud logs &amp;lt;deployment-id&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scale to zero, if your agent is bursty
&lt;/h2&gt;

&lt;p&gt;Most agents are not busy. They wake up on a webhook, a schedule, or someone typing, do a few minutes of work, and go quiet. Paying for an instance that sits idle 22 hours a day is the default cost of agent hosting on most stacks.&lt;/p&gt;

&lt;p&gt;Deploy with &lt;code&gt;--min-instances 0&lt;/code&gt; and the service scales down when nothing is calling it, then scales back up on the next request. Compute meters only while an instance is actually running. Two honest caveats: anything you keep, like stored data, bills whether the agent is awake or not, and an agent that has to react within seconds of an event should keep a floor of one instance rather than paying a cold start on every trigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that gets interesting
&lt;/h2&gt;

&lt;p&gt;Your agent is now running on infrastructure. It can also operate that infrastructure.&lt;/p&gt;

&lt;p&gt;We run a hosted &lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP&lt;/a&gt; server at &lt;code&gt;api.scalix.world/v1/mcp&lt;/code&gt; that exposes the platform as 55 tools: run queries and migrations, branch a database, deploy a service, check status and spend. One API key authorizes all of it, and that same key covers database, storage, functions, AI inference, and the registry. Point your deployed agent at it and the tools become things it can do.&lt;/p&gt;

&lt;p&gt;Which means an agent can provision the database it needs for a new task, spin up a second service to handle a workload, check whether its deploys landed, and check what all of that cost. It is the same capability we wrote about when a &lt;a href="https://dev.to/blog/deploy-with-claude-code"&gt;coding agent deploys your app&lt;/a&gt;, except the agent doing the operating is the one you deployed. Give that scoped keys and approval gates on the destructive actions, the way you would with any other operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we are
&lt;/h2&gt;

&lt;p&gt;Being straight about the stage: one EU region today, India next. When something breaks you get the two engineers who built it rather than a support tier. We publish uptime at &lt;a href="https://status.scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;status.scalix.world&lt;/a&gt; so you can check the claim rather than take it.&lt;/p&gt;

&lt;p&gt;If you have an agent on your laptop that should be running somewhere else, &lt;a href="https://scalix.world/run?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; is where to put it. Deploy it, point it at the MCP server, and let it run its own infrastructure. Come tell us what breaks on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploy an MCP Server on Docker</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/deploy-an-mcp-server-on-docker-423n</link>
      <guid>https://dev.to/scalixworld/deploy-an-mcp-server-on-docker-423n</guid>
      <description>&lt;p&gt;You have an MCP server. It runs on your machine, an agent on that same machine calls its tools, and it works. Now you want it in a container, so it behaves identically on your laptop, in CI, and on a server, with a dependency set that does not drift out from under you.&lt;/p&gt;

&lt;p&gt;Docker is the right shape for this. An MCP server that speaks streamable HTTP is an ordinary long-running web service, and a container is the ordinary way to ship one. This is the short version: why to containerize, a Dockerfile that works, the local run, the deploy that gets you an HTTPS URL, and how to point an agent at it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Docker for an MCP server
&lt;/h2&gt;

&lt;p&gt;Two reasons, and neither one is fashion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolation.&lt;/strong&gt; An MCP server exists to run tool calls on behalf of an agent. That is the whole point of it, and it is also the risk: the code deciding which tool to run is a model, and the arguments arrive from a conversation. You want that executing inside a boundary that is not your user account. A container gives it a filesystem, a process tree, and a network namespace that are not your machine's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reproducibility.&lt;/strong&gt; MCP servers collect the boring kind of dependency. A runtime version, a system library one of your tools shells out to, a CA bundle, a locale. Pin them into an image and the server behaves the same everywhere it runs. Skip it and "works on my laptop" becomes a real support burden the first time a teammate's agent connects.&lt;/p&gt;

&lt;p&gt;There is a third reason that only shows up later. A container is a deployable unit, so once the server is an image, &lt;a href="https://dev.to/blog/how-to-host-an-mcp-server"&gt;hosting it&lt;/a&gt; is a deploy rather than a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before the Dockerfile: check your transport
&lt;/h2&gt;

&lt;p&gt;One prerequisite. Your server has to speak streamable HTTP, not stdio.&lt;/p&gt;

&lt;p&gt;A stdio server is launched as a subprocess by a client on the same machine and talks over standard input and output. Putting that in a container and exposing a port solves nothing, because nothing is listening on the port. If yours is still stdio, swap the transport first. Most frameworks support both, so it is usually configuration rather than a rewrite, and we walked through the difference in &lt;a href="https://dev.to/blog/remote-vs-local-mcp-servers"&gt;remote vs local MCP servers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Two lines of your server code matter more than the rest of the Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`MCP server listening on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bind to &lt;code&gt;0.0.0.0&lt;/code&gt;, not &lt;code&gt;127.0.0.1&lt;/code&gt;. A server bound to localhost inside a container is reachable only from inside that container, and every client outside sees a refused connection. Read the port from the environment so the host can move it without a rebuild.&lt;/p&gt;

&lt;h2&gt;
  
  
  A minimal Dockerfile
&lt;/h2&gt;

&lt;p&gt;Node example. The same structure applies to Python, Go, or Rust: build in one stage, run in a slim second stage, drop root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax=docker/dockerfile:1&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:22-slim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:22-slim&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm cache clean &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/dist ./dist&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;useradd &lt;span class="nt"&gt;--system&lt;/span&gt; &lt;span class="nt"&gt;--uid&lt;/span&gt; 10001 mcp
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; mcp&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT=8080&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "dist/server.js"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The choices worth explaining. The build stage is separate so compilers and dev dependencies never reach the shipped image. The runtime runs as a non-root user, because a process executing model-chosen tool calls should not be root even inside a container. &lt;code&gt;PORT&lt;/code&gt; is an environment variable with a default rather than a hardcoded number. Nothing secret is copied in.&lt;/p&gt;

&lt;p&gt;That last point is the one people get wrong. Images get pushed to registries and pulled onto machines you do not own. Anything you &lt;code&gt;COPY&lt;/code&gt; into an image is not a secret anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; mcp-server:v1 &lt;span class="nb"&gt;.&lt;/span&gt;

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MCP_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MCP_API_KEY&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  mcp-server:v1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then confirm it actually answers on the network, not just in the logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:8080/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MCP_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that hangs or refuses, it is the bind address nine times out of ten. Point a local client at the same URL and check the tool list before you deploy anything. A broken tool schema is much cheaper to find here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy the container somewhere always-on
&lt;/h2&gt;

&lt;p&gt;Local Docker buys you reproducibility. It does not buy you reachability. Your laptop is still not a server, and an agent cannot call a URL that stops existing when you close the lid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://scalix.world/run?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; deploys containers, either from an image you built or straight from source. Tag and push under your project id, which is the registry namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SCALIX_API_KEY&lt;/span&gt; | docker login api.scalix.world &lt;span class="nt"&gt;-u&lt;/span&gt; scalix &lt;span class="nt"&gt;--password-stdin&lt;/span&gt;

docker tag mcp-server:v1 api.scalix.world/&amp;lt;project-id&amp;gt;/mcp-server:v1
docker push api.scalix.world/&amp;lt;project-id&amp;gt;/mcp-server:v1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then deploy it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scalix-cloud run deploy &lt;span class="nt"&gt;--name&lt;/span&gt; mcp-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; api.scalix.world/&amp;lt;project-id&amp;gt;/mcp-server:v1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-instances&lt;/span&gt; 0 &lt;span class="nt"&gt;--max-instances&lt;/span&gt; 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service comes up at a stable HTTPS address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://mcp-server.run.scalix.world

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you would rather not build the image at all, deploy from source and let the platform detect the runtime from your project. It recognizes Node, Python, Go, Rust, or a Dockerfile. Keep the Dockerfile anyway. It is the version of the build you control.&lt;/p&gt;

&lt;p&gt;One note on &lt;code&gt;--min-instances 0&lt;/code&gt;. That is scale to zero: no instances running, nothing to pay for, while no agent is calling. The usual objection is cold starts, and it is a fair one for a server an agent hits interactively. The microVM itself boots in roughly 76ms; add your server's own startup on top and the first call after an idle period lands in a couple of seconds, not the long pause that phrase usually implies. If your server holds warm state between calls, set the floor to 1 instead and skip the question.&lt;/p&gt;

&lt;p&gt;Every deploy is a revision, so a bad image is one command away from undone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scalix-cloud run rollback &amp;lt;service-id&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Point an agent at it
&lt;/h2&gt;

&lt;p&gt;It is a URL now, so any MCP client can connect. In Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http my-mcp https://mcp-server.run.scalix.world/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MCP_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use whatever path you mounted the transport on. Confirm with &lt;code&gt;claude mcp list&lt;/code&gt;, or &lt;code&gt;/mcp&lt;/code&gt; inside a session, which shows the connection status and the tools it picked up. Add &lt;code&gt;--scope project&lt;/code&gt; to check the connection into a shared &lt;code&gt;.mcp.json&lt;/code&gt; so teammates get it too. Cursor and other MCP clients take the same two inputs: a URL and a header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth is not optional now
&lt;/h2&gt;

&lt;p&gt;The moment your server has a public URL, every tool it exposes is public too. A stdio server needed no network auth because the trust boundary was your machine. An HTTP one has no such luck.&lt;/p&gt;

&lt;p&gt;The workable default is a bearer token. Your server reads the &lt;code&gt;Authorization&lt;/code&gt; header on every request, compares it against a key you issued, and rejects anything else. Keep the key in the environment, rotate by issuing a new one and retiring the old. The Model Context Protocol also defines an &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;OAuth 2.1 based authorization model&lt;/a&gt; for HTTP transports, which is where you go when the callers are real end users rather than your own agents.&lt;/p&gt;

&lt;p&gt;Whichever you pick, run the check before dispatching the tool call, not after it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When not to self-host at all
&lt;/h2&gt;

&lt;p&gt;Worth saying plainly, because a container tutorial has an obvious bias. Sometimes the correct amount of MCP server to run is none.&lt;/p&gt;

&lt;p&gt;If what you want is tools for your cloud, so an agent can deploy a service or work a database, that server already exists and building it is wasted work. Scalix runs a hosted &lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP server&lt;/a&gt; at &lt;code&gt;api.scalix.world/v1/mcp&lt;/code&gt; that exposes the platform as 55 tools, with one API key authorizing all of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http scalix https://api.scalix.world/v1/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$SCALIX_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing to build, nothing to host, no Dockerfile. Write and containerize your own when the tools are genuinely yours: internal APIs, your own data, domain logic nobody else has. That is when everything above earns its place. The longer version of that decision is in &lt;a href="https://dev.to/blog/how-to-host-an-mcp-server"&gt;how to host an MCP server&lt;/a&gt;, and what an agent can actually do once it has cloud tools is in &lt;a href="https://dev.to/blog/deploy-with-claude-code"&gt;deploy with Claude Code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Containerizing an MCP server is not an MCP problem. It is the same job as containerizing any long-running service: pin the runtime, bind &lt;code&gt;0.0.0.0&lt;/code&gt;, read &lt;code&gt;PORT&lt;/code&gt;, drop root, keep secrets out of the image. What is specific to MCP comes after the build, because the process in that container executes tool calls a model chose, which is why the isolation is doing real work and the auth is not a nice-to-have.&lt;/p&gt;

&lt;p&gt;Build the image, run it locally, push it, deploy it, hand your agent the URL. You can start free at &lt;a href="https://scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;scalix.world&lt;/a&gt; with no card, and if you get stuck on the deploy, come find us on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>devops</category>
      <category>docker</category>
      <category>mcp</category>
    </item>
    <item>
      <title>How to Deploy with Claude Code (to a real cloud)</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/how-to-deploy-with-claude-code-to-a-real-cloud-3jdn</link>
      <guid>https://dev.to/scalixworld/how-to-deploy-with-claude-code-to-a-real-cloud-3jdn</guid>
      <description>&lt;p&gt;You have used Claude Code to write an app. It scaffolded the project, wrote the handlers, fixed its own bugs, and the thing runs on your laptop. Then you hit the wall every coding agent hits: it can write the code, but it cannot ship it. Deploying is still your job, in a different terminal, by hand.&lt;/p&gt;

&lt;p&gt;That wall is not a Claude Code limitation. It is a missing connection. An agent can only act on the systems it has tools for, and by default it has no tools for your cloud. Give it those tools and "deploy with Claude Code" stops being a figure of speech. The agent provisions the database, pushes the app, and hands you a live URL, without leaving the conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap between writing code and shipping it
&lt;/h2&gt;

&lt;p&gt;A coding agent is good at the part that happens inside your repository. It reads files, edits them, runs your tests, and reasons about what broke. All of that lives on your machine, which is exactly where the agent already has reach.&lt;/p&gt;

&lt;p&gt;Shipping is different. To deploy an app you have to talk to a cloud: create a service, provision a database, push an image, wire up an environment variable, read back a status. Those are actions on a system outside the repository, and an agent cannot take an action it has no tool for. So it writes a perfect deploy script and then asks you to run it. Close, but you are still the one shipping.&lt;/p&gt;

&lt;p&gt;The fix is to hand the agent real tools for your cloud. That is what the &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; is for, and it is what turns "generate a deploy command" into "deploy an app with an AI agent."&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect Claude Code to a hosted MCP server
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP&lt;/a&gt; is an open standard for giving an agent tools it can call. An &lt;a href="https://dev.to/blog/what-is-an-mcp-server"&gt;MCP server&lt;/a&gt; exposes a set of actions, and an MCP client, which is what Claude Code is, calls them. Point Claude Code at a server and its tools become things the agent can do, not just describe.&lt;/p&gt;

&lt;p&gt;Scalix runs a hosted MCP server for exactly this. It sits at &lt;code&gt;api.scalix.world/v1/mcp&lt;/code&gt; and exposes the platform as 55 tools: run queries and migrations, branch a database, deploy a service, check status, and so on. One API key authorizes all of it. Because the server is hosted and always on, you run and maintain nothing to use it. (If you would rather host your own MCP server instead, we wrote a &lt;a href="https://dev.to/blog/how-to-host-an-mcp-server"&gt;full guide&lt;/a&gt; to that.)&lt;/p&gt;

&lt;p&gt;Connecting Claude Code to an MCP server takes one command. Grab a Scalix API key from the console, then add the server over HTTP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http scalix https://api.scalix.world/v1/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$SCALIX_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That registers the Scalix server for the current project. Add &lt;code&gt;--scope project&lt;/code&gt; to share the connection with your team through a checked-in &lt;code&gt;.mcp.json&lt;/code&gt;, or &lt;code&gt;--scope user&lt;/code&gt; to make it available in every project on your machine.&lt;/p&gt;

&lt;p&gt;Confirm the agent can see it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp list

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside a session, &lt;code&gt;/mcp&lt;/code&gt; shows the connection status and how many tools it picked up. Once it reports connected, Claude Code has a working set of cloud tools. There is nothing to install. Claude Code MCP setup is a URL and a key, and the tools show up in the session.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent can do once it is connected
&lt;/h2&gt;

&lt;p&gt;With the Scalix tools available, the agent's reach extends past your repository and into your cloud. In plain language, you can now ask it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Set up and work the database.&lt;/strong&gt; The agent creates a Postgres instance through the platform API with the same key, reads back the connection string, and from there the MCP tools take over: run queries, inspect the schema, apply migrations, spin up a database branch to test something risky. The same agent that writes the code querying a database can now stand up and operate the database it queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy to Scalix Run.&lt;/strong&gt; The agent builds or references a container image and creates a running service from it, then returns the URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read status.&lt;/strong&gt; It can check whether a deploy succeeded and see whether a service is healthy, which means it can also react when something is wrong. For the full log stream, &lt;code&gt;scalix-cloud logs&lt;/code&gt; is a CLI command like any other, and a coding agent can run those too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one matters more than it looks. An agent that can only fire off actions is a fancy script. An agent that can also read back what happened can deploy, notice the deploy failed, fix the code, and redeploy on its own. That loop is the difference between generating a deploy command and actually shipping.&lt;/p&gt;

&lt;h2&gt;
  
  
  A deploy walkthrough
&lt;/h2&gt;

&lt;p&gt;Here is the concrete version. You have an app in your repo, the Scalix MCP server connected, and you want it live. Ask the agent, in the session, to ship it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Deploy this app to Scalix Run. It listens on port 8080. Provision a Postgres database, pass the connection string in as an environment variable, and give me the URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent works through the tools in order: it detects the runtime, provisions the database, deploys the service, wires the connection string into the environment, and reports back. Scalix Run deploys straight from source and recognizes Node, Python, Go, Rust, or a Dockerfile, so if the agent just wrote the code, there is no separate build step to babysit.&lt;/p&gt;

&lt;p&gt;The deploy itself maps to the same run command you would type by hand. With a prebuilt image it looks like this (the registry namespaces images under your project id):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scalix-cloud run deploy &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; api.scalix.world/&amp;lt;project-id&amp;gt;/my-app:v1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-instances&lt;/span&gt; 1 &lt;span class="nt"&gt;--max-instances&lt;/span&gt; 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You did not run it. The agent did the equivalent through MCP, which is the whole point. When it finishes, the service is live at a stable URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://my-app.run.scalix.world

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here the loop stays inside the conversation. Tell it the app is throwing a 500 and it can check the status, pull logs through the CLI, patch the code, and redeploy without you switching tools. You describe the outcome; the agent operates the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Deploying with Claude Code is not a special mode or a new product. It is your agent, plus tools for a real cloud, connected over one open protocol. Write the code in the session you already use, then let the same agent provision the database and put the app online, and read back whether it worked.&lt;/p&gt;

&lt;p&gt;If you want to try it, &lt;a href="https://scalix.world/run" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; is the service the agent deploys to, and &lt;a href="https://scalix.world/coder" rel="noopener noreferrer"&gt;Scalix Coder&lt;/a&gt; is our own coding agent on the same platform if you would rather not bring your own. Point an agent at the MCP server, describe what you want live, and let it ship.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>PostgreSQL 16, 17, and 18 on a Serverless Engine</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/postgresql-16-17-and-18-on-a-serverless-engine-2823</link>
      <guid>https://dev.to/scalixworld/postgresql-16-17-and-18-on-a-serverless-engine-2823</guid>
      <description>&lt;p&gt;On most managed Postgres, choosing a major version is a dropdown you touch once. You pick something recent, you forget about it, and eighteen months later a maintenance window quietly moves you along.&lt;/p&gt;

&lt;p&gt;On a serverless engine that choice behaves differently, and it took us a while to say clearly why. When a database can branch, restore to a timestamp, and suspend to nothing between connections, the major version stops being a property of a running server. It becomes a property of the data.&lt;/p&gt;

&lt;p&gt;ScalixNova now offers PostgreSQL 16, 17, and 18. Here is what that means once compute and storage are separated, and what we have not solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking a version
&lt;/h2&gt;

&lt;p&gt;You choose the major at creation, and only at creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.scalix.world/v1/databases &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$SCALIX_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{ "name": "prod", "pg_version": "18" }'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Omit &lt;code&gt;pg_version&lt;/code&gt; and you get 16, the default. Ask for something unavailable and you get a &lt;code&gt;400&lt;/code&gt; whose message lists the set that is available. The failure mode we refused to ship was the silent downgrade: you request 18, the platform hands you whatever binaries the host happens to have, and you find out during a migration that needs a feature your server does not have.&lt;/p&gt;

&lt;p&gt;The supported set comes from one shared definition read at two edges: the gateway validates your request before a database exists, and the compute plane uses the same list to select server binaries. There is no gap where the API accepts a version the compute layer cannot start. For operators running Scalix on their own hardware that list is configuration rather than a rebuild, so a host without a given major fails closed instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The version is part of the data's identity
&lt;/h2&gt;

&lt;p&gt;A ScalixNova database has no long lived server process to attach a version to. Compute is acquired when you connect and released when you are done. What persists is the data directory, the base backups, and the archived write ahead log. So the question "what version is this database" cannot be answered by asking a running process. It has to be answered by the storage.&lt;/p&gt;

&lt;p&gt;Postgres already solved this and we use its answer. &lt;code&gt;initdb&lt;/code&gt; stamps the major into &lt;code&gt;PG_VERSION&lt;/code&gt; in the data directory, and every path that starts a server against existing data reads that file to choose binaries. Cold start, branch, restore from a base backup, replay to an LSN: all of them resolve the major from the data, not from the request that triggered them.&lt;/p&gt;

&lt;p&gt;The practical rule that falls out is: the backup's major wins. If a base backup came off a 17 server, it is replayed by 17 binaries, even if the environment around it has a different opinion. That is the only version of this that is safe, because Postgres itself will refuse to start otherwise, and the alternative is a restore that fails at the worst possible moment.&lt;/p&gt;

&lt;p&gt;The same logic runs one layer up. &lt;code&gt;pg_basebackup&lt;/code&gt; is version matched per worker to the server it backs up, because a 16 client cannot take a base backup of a 17 or 18 server. On a single version fleet you never notice this. With three majors live at once it is a correctness requirement, and getting it wrong is quiet: it produces a database with no base backup, and therefore no restore point.&lt;/p&gt;

&lt;p&gt;One smaller detail in the same spirit: &lt;code&gt;initdb --data-checksums&lt;/code&gt; is explicit on every major we run. Postgres 18 turns data checksums on by default and 16 and 17 do not, so leaving it implicit would give you a fleet where checksum behaviour depends on the year a database was created.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stays boring
&lt;/h2&gt;

&lt;p&gt;None of this should reach your application, and it does not.&lt;/p&gt;

&lt;p&gt;ScalixNova is a purpose-built storage engine that speaks the PostgreSQL wire protocol. It is not a managed wrapper around upstream Postgres, and it is not a fork. We wrote the engine deliberately, for reasons we go into in &lt;a href="https://dev.to/blog/built-not-assembled"&gt;built, not assembled&lt;/a&gt;. From your side of the socket the contract is the one you already know:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgresql://t_a1b2c3d4e5f6:YOUR_API_KEY@db.scalix.world:6432/db_a1b2c3d4e5f6?sslmode=require

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A standard DSN. &lt;code&gt;psql&lt;/code&gt; connects. &lt;code&gt;node-postgres&lt;/code&gt;, &lt;code&gt;psycopg&lt;/code&gt;, SQLAlchemy, Prisma, Drizzle, and your migration tool connect. TLS is required, not optional, and connections without it are rejected. Your database role is a per database &lt;code&gt;NOSUPERUSER&lt;/code&gt; role, assigned automatically.&lt;/p&gt;

&lt;p&gt;The extension set is the same on every supported major. pgvector, pg_trgm, uuid-ossp, and the contrib set are available whether you picked 16 or 18, so the version choice does not quietly become an extension choice.&lt;/p&gt;

&lt;p&gt;Everything version related is a control plane operation. Creating databases, branching, and restores go through the API, the CLI, or the SDK. Running SQL goes through your driver, unchanged. Keeping that boundary clean is why the client half of this post is so short.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branches, restores, and why the major is fixed
&lt;/h2&gt;

&lt;p&gt;The rule is: the major is fixed for the life of the database, and everything derived from that database inherits it.&lt;/p&gt;

&lt;p&gt;Branch databases are isolated, carry their own scoped token and a TTL so scratch environments expire instead of accumulating, and run the same major as the parent. Point in time restores are the same story: base backups plus archived WAL, on a five minute bound while the database is active, with the open segment shipped when it suspends. A restore targeting a moment after the last archived point returns a &lt;code&gt;409&lt;/code&gt; rather than silently handing you older data and calling it success.&lt;/p&gt;

&lt;p&gt;Now consider what a mutable major would do to that. You have a database created on 16 and upgraded to 18 last month, and you restore to a timestamp from six weeks ago. Which binaries replay that WAL? There is no good answer. Physical WAL is not portable across majors, so a mutable major silently truncates your restore window at the upgrade boundary, and the truncation is invisible until you need it.&lt;/p&gt;

&lt;p&gt;Pinning the major keeps the recovery window honest. Every point inside your retention is reachable with the binaries that wrote it.&lt;/p&gt;

&lt;p&gt;A paused database also does not bill compute, which is a consequence of acquiring compute per connection rather than a Postgres feature. It is what makes "run 18 alongside your 16 for a while" a practical suggestion instead of a theoretical one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we have not solved
&lt;/h2&gt;

&lt;p&gt;Fixing the major has a cost, and it is ours to state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are no in place major upgrades.&lt;/strong&gt; To move from 16 to 18 you create a database on 18 and migrate with &lt;code&gt;pg_dump&lt;/code&gt; and &lt;code&gt;pg_restore&lt;/code&gt;, or with logical replication for a smaller cutover window. A managed blue and green cutover built on branching is roadmap, and roadmap is not product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The dedicated tier runs 16 only.&lt;/strong&gt; Multi version is generally available on the shared tier. The dedicated microVM tier is still on 16 and fails closed on other majors rather than starting something it cannot support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The default deliberately trails the newest.&lt;/strong&gt; New databases get 16, not 18. New majors arrive within roughly 90 days of community GA once the extension set is validated on them, each is supported to its community end of life, and default changes are announced ahead and never touch existing databases. If you want 18, ask for 18. We will not move you there while you are not looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you run Postgres for a living, the question about any serverless engine is whether the boring guarantees hold. Which binaries replay your WAL. What happens when you ask for a version that is not there. Whether a restore can quietly return the wrong thing.&lt;/p&gt;

&lt;p&gt;You can create a database on 16, 17, or 18 and check those yourself at &lt;a href="https://scalix.world/nova?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;Scalix Nova&lt;/a&gt;, without a card, on a one time trial credit. If you find a case where the version guarantee does not hold, we want to hear about it. Find us on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://x.com/scalix_world" rel="noopener noreferrer"&gt;X&lt;/a&gt;, and you will be talking to the two people who wrote the engine.&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How durability works in a storage engine we wrote ourselves</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/how-durability-works-in-a-storage-engine-we-wrote-ourselves-jd8</link>
      <guid>https://dev.to/scalixworld/how-durability-works-in-a-storage-engine-we-wrote-ourselves-jd8</guid>
      <description>&lt;p&gt;Durability is the most overloaded word on a database landing page. Sometimes it means "we take nightly backups." Sometimes it means "we replicate." Occasionally it means "we have not lost anything yet."&lt;/p&gt;

&lt;p&gt;None of those are the same guarantee, and the difference between them is what you need to know before putting state on someone else's infrastructure.&lt;/p&gt;

&lt;p&gt;We wrote the storage engine, so we can be precise. ScalixNova speaks the PostgreSQL wire protocol, but underneath it is our own write ahead log rather than a managed wrapper around an upstream distribution. This post walks the write path and says what "durable" means at each boundary it crosses.&lt;/p&gt;

&lt;p&gt;A write moves through four states. The engineering that matters lives in the transitions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Accepted&lt;/strong&gt; by the log's current term holder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flushed&lt;/strong&gt; and fsync'd into a WAL segment on local disk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archived&lt;/strong&gt; as a closed segment in object storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restorable&lt;/strong&gt; to a point in time&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Accepted: term fencing on a single writer
&lt;/h2&gt;

&lt;p&gt;The log has exactly one writer at a time. That writer holds a &lt;em&gt;term&lt;/em&gt;, a monotonically increasing number. Every append carries the proposer's term, and the acceptor compares it against the term it currently honours:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proposer term lower than current: reject with a stale proposer error. Nothing touches the disk.&lt;/li&gt;
&lt;li&gt;Proposer term higher: adopt the new term, then accept.&lt;/li&gt;
&lt;li&gt;Equal: accept.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The obvious objection is that a single writer cannot split-brain by definition. It can, and that is the failure fencing exists for. The problem is not two writers running concurrently by design. It is one writer that has already been replaced, does not know it, and comes back holding a stale view of the log. A long garbage collection pause, a partitioned network, a slow restart after an operator action: any of those produce a process that still believes it is the writer.&lt;/p&gt;

&lt;p&gt;Without fencing, that process appends after its successor already did, and you get one log with two divergent futures at the same LSN. Nothing in the byte stream tells you which branch is real. With fencing, its very first append is rejected on the term comparison, before a single byte is written.&lt;/p&gt;

&lt;p&gt;Term is not just an in-memory counter. It is persisted alongside flush LSN, commit LSN and remote consistent LSN in the timeline metadata, written through a crash safe path: write a temp file, fsync it, rename over the target, then fsync the parent directory. After a crash the acceptor comes back knowing which term it last honoured. A stale proposer cannot win simply by outliving a restart.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Flushed: fsync, then acknowledge
&lt;/h2&gt;

&lt;p&gt;An append computes the segment number and offset from the LSN, opens the segment file, seeks, writes, and calls &lt;code&gt;sync_all()&lt;/code&gt; before returning. The flush LSN advances only after that fsync returns. If a record spans a segment boundary, each segment is fsync'd in turn.&lt;/p&gt;

&lt;p&gt;There is a second rule in the append path that does more work than it looks like. Appends must be contiguous. If the incoming start LSN is not exactly the current flush LSN, the append is rejected with a gap error rather than written at the requested offset. A WAL with a hole in it is not a WAL. Refusing the gap at the append boundary means the recovery path never has to reason about what might be missing in the middle.&lt;/p&gt;

&lt;p&gt;This is the layer where "durable" means what an SRE means by it. The bytes are on the device, and the acknowledgement is emitted after the fsync rather than before it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Archived: local disk is one machine's opinion
&lt;/h2&gt;

&lt;p&gt;An fsync'd segment survives a process crash. It does not survive the machine. Durability against machine loss means the log has to leave the machine, so two things go to object storage: base backups, and WAL segments as they close.&lt;/p&gt;

&lt;p&gt;Which makes the interesting question not "do you archive" but "how far behind is the archive allowed to fall." Three bounds answer that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;While the database is active&lt;/strong&gt; , the log is forced to switch segments on a five minute interval. A segment closes and ships whether or not write volume happened to fill it. Low traffic databases do not get a worse recovery point than busy ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a database suspends&lt;/strong&gt; , the open segment ships as part of the suspend path. Scale to zero is normal operation here, so the tail of the log cannot sit stranded on a machine waiting for a database that is not going to wake up on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When the compute layer shuts down&lt;/strong&gt; , it takes a base backup of every active worker before exiting, under a bounded deadline. A deploy is a planned event, and a planned event should not cost you a recovery point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together those put the most recent restorable point within roughly five minutes of your latest write while the database is active.&lt;/p&gt;

&lt;p&gt;Alongside the segments we write a recovery catalog: points carrying LSN, timestamp and the segments needed to reach them, plus the earliest and latest recoverable LSN and time. Recovery has to know which segments it needs before it starts pulling them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Restorable: what recovery actually offers
&lt;/h2&gt;

&lt;p&gt;Two operations, kept deliberately distinct because they answer different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Restore to a timestamp.&lt;/strong&gt; &lt;code&gt;POST /api/v1/tenants/{tenant_id}/pitr/restore&lt;/code&gt; restores by wall clock time, or to the latest recoverable point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branch at an LSN.&lt;/strong&gt; &lt;code&gt;POST /api/v1/tenants/{tenant_id}/timelines/{timeline_id}/branch&lt;/code&gt; with a &lt;code&gt;branch_lsn&lt;/code&gt; creates an independent timeline at a specific position in the log.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both run the same machinery: pull the base backup, replay archived WAL forward to the target, bring up a fresh compute worker pointed at the result. A branch is a point in time restore you keep, addressed by LSN instead of by clock. It gets its own worker and its own backup cycle, and writes on it never reach the parent. Deleting one purges its base backups and archived WAL and reports the object count reclaimed.&lt;/p&gt;

&lt;p&gt;The failure mode we thought hardest about is asking to restore to a moment &lt;em&gt;after&lt;/em&gt; the last archived point. Quietly handing back older data is the worst available answer, because the restore reports success and the gap only surfaces later, in your data. That request returns a &lt;code&gt;409&lt;/code&gt; with guidance instead.&lt;/p&gt;

&lt;p&gt;Retention defaults to seven days and is configurable per tenant. Separately from the continuous path, nightly encrypted backups are replicated off site to EU located storage. Routine restore drills for that off site path are still being operationalized, and we would rather say so than imply a rehearsed process we do not have yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we do not have yet
&lt;/h2&gt;

&lt;p&gt;Precision cuts both ways, so here is the other half.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-node quorum is not wired.&lt;/strong&gt; Term fencing, shard placement and the quorum commit LSN calculation are written and tested. The commit function sorts acceptor flush LSNs and returns the highest LSN acknowledged by at least a quorum. It is not running across nodes, and the reason is worth stating plainly: the gRPC accept path returns &lt;code&gt;unimplemented&lt;/code&gt; on purpose. The protobuf message for WAL data carries no term field, so accepting there would mean inventing a term, and an invented term either wrongly rejects a legitimate proposer after recovery or silently overwrites a higher one. That is the exact failure mode fencing prevents, so refusing beats faking success. Single node writes go over the binary protocol, which carries a real term. When quorum lands, it lands on fencing that is already there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One region.&lt;/strong&gt; One EU region today. Losing it is a restore from off-site backup, not a failover. We would rather say that than imply a topology we do not run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restorability introspection is incomplete.&lt;/strong&gt; The endpoint that would tell you how far back you can currently restore returns a &lt;code&gt;501&lt;/code&gt; saying it needs the WAL archive catalog. It could return a plausible looking window instead. A recovery bound you cannot verify is worse than no answer, because someone will plan against it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Durability is scoped to the project timeline.&lt;/strong&gt; Backups, branches and point in time recovery operate on the project's timeline, which is how the console labels them. Per database granularity within a project is roadmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support is the two of us.&lt;/strong&gt; We are two engineers running our own European infrastructure. The people who wrote the WAL path are the people who answer when you ask about it.&lt;/p&gt;

&lt;p&gt;Every one of those is a real limit, and every one is easier to close than a durability model that was assumed rather than designed. That is the trade we made when we &lt;a href="https://dev.to/blog/built-not-assembled"&gt;built the platform instead of assembling it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The recovery semantics above are documented at &lt;a href="https://docs.scalix.world/database/backups?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;docs.scalix.world/database/backups&lt;/a&gt;. To run a restore yourself, you can start without a card on a one time trial credit at &lt;a href="https://scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;scalix.world&lt;/a&gt;. If you would rather argue with the design first, we are on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;, and that is a conversation we want.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>database</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Built, not assembled</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Wed, 29 Jul 2026 09:00:16 +0000</pubDate>
      <link>https://dev.to/scalixworld/built-not-assembled-f3m</link>
      <guid>https://dev.to/scalixworld/built-not-assembled-f3m</guid>
      <description>&lt;p&gt;Most cloud platforms are not platforms. They are holding companies.&lt;/p&gt;

&lt;p&gt;A database startup gets acquired. A serverless product gets bolted on. An AI inference layer arrives via partnership. Storage, auth, CDN -- each built by a different team, on different assumptions, with different data models. They get unified at exactly one layer: billing. You get one invoice. Underneath, six systems that do not know about each other.&lt;/p&gt;

&lt;p&gt;You feel the seams. Auth tokens from the identity service do not propagate cleanly to the database layer. Metering in compute runs at a different granularity than metering in storage. Scale-to-zero works for functions but not databases, or it works for databases but not the way your functions expect. Your first week is spent wiring things together that should already be wired.&lt;/p&gt;

&lt;p&gt;We built Scalix World as one system. Two engineers who decided that the integration layer is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The storage engine
&lt;/h2&gt;

&lt;p&gt;ScalixNova is not a managed wrapper around upstream Postgres. It is a purpose-built storage engine that speaks the Postgres wire protocol, with a term-fenced, fsync-durable write-ahead log at its core. We designed it from day one for Paxos-style quorum replication as we grow from one region to many, rather than bolting replication on later as an afterthought. Durability correctness is the foundation of the storage layer, not a feature we added.&lt;/p&gt;

&lt;p&gt;What that means in practice: ScalixNova shares the same identity system and metering pipeline as every other Scalix World service. The API key that calls a function also connects to your database. The compute units your database consumes show up on the same bill as your function invocations and AI tokens. There is no impedance mismatch because there was never a boundary to bridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The isolation model
&lt;/h2&gt;

&lt;p&gt;Functions and containers on Scalix World do not run in shared-kernel containers. Each workload gets its own microVM -- a lightweight virtual machine with hardware-level isolation, its own kernel, its own memory boundary. MicroVMs boot in roughly 76ms. This is not a premium tier. It is the default for every function invocation and every container deployment.&lt;/p&gt;

&lt;p&gt;Because the microVM lifecycle is managed by the same orchestration layer that manages databases and storage, scale-to-zero works uniformly. A cold function does not tick. Neither does a paused database. The system does not need to keep resources warm across service boundaries because there are no service boundaries to keep warm across.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gateway
&lt;/h2&gt;

&lt;p&gt;Every request to Scalix World -- database connection, function invocation, AI inference call, storage operation -- enters through one gateway. That gateway authenticates against one identity system, meters usage into one ledger, and routes to the appropriate backend.&lt;/p&gt;

&lt;p&gt;This sounds simple. It is deceptively hard to get right and nearly impossible to retrofit. When services arrive by acquisition, each brings its own auth model, its own session semantics, its own usage tracking. Unifying those retroactively means translation layers. Translation layers are where bugs, inconsistencies, and security gaps live.&lt;/p&gt;

&lt;p&gt;We did not unify anything. We built one identity system, one metering pipeline, and one gateway from the start. A single API key works across every service not because we mapped keys between systems, but because there is one system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What falls out of this
&lt;/h2&gt;

&lt;p&gt;The practical consequence of one-system architecture is that primitives compose without glue.&lt;/p&gt;

&lt;p&gt;An AI agent with a single API key can provision a database, store data, invoke a function, call an AI model, and check its own usage. Same authenticated session, same metering, same project context. No cross-service token exchange. No credential federation. No billing reconciliation job running overnight.&lt;/p&gt;

&lt;p&gt;Scale-to-zero works the same way everywhere because every service shares the same lifecycle management. When nothing runs, nothing meters. No service opted out because it was acquired before that pattern existed.&lt;/p&gt;

&lt;p&gt;The bill is coherent because it comes from one meter, not from six usage databases reconciled after the fact.&lt;/p&gt;

&lt;p&gt;These are not features. They are properties that emerge from building one system instead of assembling six.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deliberate scope
&lt;/h2&gt;

&lt;p&gt;We built this with two people, in Rust, on dedicated European infrastructure we operate. That is a statement about scope, not velocity.&lt;/p&gt;

&lt;p&gt;We chose fewer primitives that work together deeply over a broad catalog of loosely integrated services. Database, compute, functions, AI inference, object storage, auth, DNS. Seven categories sharing one identity layer, one gateway, one metering system. The alternative -- wrapping existing open-source projects behind a unified API -- would have shipped faster and covered more ground. It would also have reproduced exactly the integration problems we set out to eliminate. Every wrapper is a seam. Every seam is where auth breaks, metering drifts, or scale-to-zero stops working.&lt;/p&gt;

&lt;p&gt;Depth over breadth. That is a trade-off and we own what it costs. One EU region today, India next. No managed Redis, no managed Kafka, no CDN -- those are roadmap, not product. No SLA yet. When something breaks, you talk to the engineers who built it. Those engineers are us.&lt;/p&gt;

&lt;p&gt;The deal we are offering is not "trust our SLA." It is: verify our uptime at &lt;a href="https://status.scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;status.scalix.world&lt;/a&gt;, start free at &lt;a href="https://scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;scalix.world&lt;/a&gt;, and tell us what to build next. We are running a founding design-partner cohort -- grandfathered pricing, direct access, a seat at the table for what gets built. If that sounds right, DM us on &lt;a href="https://x.com/scalix_world" rel="noopener noreferrer"&gt;X&lt;/a&gt; or find us on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cloud</category>
      <category>engineering</category>
      <category>database</category>
    </item>
    <item>
      <title>One key, one bill: the economics of an integrated cloud</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Thu, 23 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/one-key-one-bill-the-economics-of-an-integrated-cloud-f5j</link>
      <guid>https://dev.to/scalixworld/one-key-one-bill-the-economics-of-an-integrated-cloud-f5j</guid>
      <description>&lt;p&gt;Before we built Scalix World, Akhil and I ran the same stack every early-stage team runs. Managed database from one vendor. AI inference endpoint from another. Serverless compute from a third. Auth from a fourth. Each individually reasonable. Together, death by a thousand idle minimums.&lt;/p&gt;

&lt;p&gt;The moment it clicked: we were paying roughly $45/month in base fees for a project with maybe fifty users. Not fifty thousand. Fifty. Most of those services sat idle most of the time, but each one had a floor -- a minimum tier ticking away whether we shipped anything that month or not.&lt;/p&gt;

&lt;p&gt;The money was not the worst part. The worst part was four dashboards, four sets of API docs, four credentials to rotate, and absolutely no way to answer "what did last Tuesday cost?" without cross-referencing four invoices.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fragmentation tax
&lt;/h2&gt;

&lt;p&gt;Every managed service has a floor. A database provider's smallest tier runs $15/month even when your app handles twelve requests a day. An AI inference endpoint charges a base fee whether anyone calls it. A compute platform's always-on container has a minimum cost. These floors exist because those platforms keep resources warm for you -- regardless of whether you use them.&lt;/p&gt;

&lt;p&gt;Then there is duplicate egress. Your function calls your database. The response flows to your AI endpoint. The AI response comes back through your function to the user. Three providers, three egress charges on the same data. The bytes do not know they are crossing billing boundaries. Your invoice does.&lt;/p&gt;

&lt;p&gt;And the cognitive overhead of managing four of everything -- four billing cycles, four support channels, four auth systems to understand when something breaks at 2 AM -- is itself a cost nobody tallies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually costs
&lt;/h2&gt;

&lt;p&gt;Here is a typical month for an indie hacker or early-stage founder running a low-traffic, bursty product across separate services. These are illustrative, rounded numbers -- not prices from any specific vendor, but representative of what entry tiers look like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line item&lt;/th&gt;
&lt;th&gt;Illustrative monthly cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Managed database (minimum tier, mostly idle)&lt;/td&gt;
&lt;td&gt;~$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI inference API (low volume, base fee + tokens)&lt;/td&gt;
&lt;td&gt;~$10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serverless compute (a few functions, light traffic)&lt;/td&gt;
&lt;td&gt;~$7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth service (small user base, near free-tier limit)&lt;/td&gt;
&lt;td&gt;~$5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object storage + CDN (a few GB)&lt;/td&gt;
&lt;td&gt;~$5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-provider egress&lt;/td&gt;
&lt;td&gt;~$3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$45/mo&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Forty-five dollars a month before you have revenue to justify it. Before you count the hours wiring four SDKs together or debugging auth token propagation between services.&lt;/p&gt;

&lt;p&gt;On Scalix World, the same workload starts on a free tier -- no credit card, no time limit. When you go to production, the Starter plan is $19/month. That covers a Postgres-compatible database, AI inference, serverless functions, object storage, auth, and DNS. One API key. One dashboard. One invoice.&lt;/p&gt;

&lt;p&gt;But the price difference is not the real story. The architecture is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero actually means zero
&lt;/h2&gt;

&lt;p&gt;When we say scale to zero, we mean the meter stops. A paused ScalixNova database does not tick at $15/month waiting for your next query. It costs nothing. A function that has not been invoked today costs nothing. An AI endpoint with no traffic costs nothing.&lt;/p&gt;

&lt;p&gt;This is not a free tier with invisible limits. It is how the platform works at every level. Every service meters at the resource level -- compute time, storage bytes, tokens processed. When the resource is idle, the charge is zero. No minimum instance. No keep-warm fee. No "base infrastructure cost" line item hiding in your bill.&lt;/p&gt;

&lt;p&gt;For bursty, agent-driven workloads, this changes the economics completely. An AI agent that runs ten minutes per hour and sleeps the rest pays for ten minutes. Not sixty.&lt;/p&gt;

&lt;h2&gt;
  
  
  One bill that tells a story
&lt;/h2&gt;

&lt;p&gt;Unified metering matters beyond cost savings. It is about being able to read your own bill.&lt;/p&gt;

&lt;p&gt;Every service on Scalix World -- database, AI, functions, storage -- meters through the same system, under the same API key, into the same ledger. When costs spike, you trace the cause to a specific service, a specific project, even a specific time window. No cross-referencing vendor dashboards.&lt;/p&gt;

&lt;p&gt;And because the metering API is part of the platform, your tools can read it too. An agent operating on Scalix World checks its own usage, queries remaining credits, and makes cost-aware decisions -- programmatically, through the same key it uses for everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest tradeoff
&lt;/h2&gt;

&lt;p&gt;We are not claiming "we are cheaper" in every scenario. At high, sustained utilization, a fixed-price provider might cost less for that specific service. We are transparent about that.&lt;/p&gt;

&lt;p&gt;The argument is narrower: for the workloads that define early-stage products and AI-native applications -- bursty, idle-heavy, unpredictable -- an integrated platform that genuinely scales to zero eliminates the floor that makes fragmented stacks expensive before you have revenue.&lt;/p&gt;

&lt;p&gt;One key across every service. One bill that makes sense. Idle costs nothing. The free tier is live at &lt;a href="https://scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;scalix.world&lt;/a&gt;, no card required. We publish our uptime openly at &lt;a href="https://status.scalix.world/?utm_source=blog&amp;amp;utm_medium=content&amp;amp;utm_campaign=launch-2026-07" rel="noopener noreferrer"&gt;status.scalix.world&lt;/a&gt;. If you want to be part of the founding design-partner cohort -- early access, grandfathered pricing, direct line to the two people building this -- DM me on &lt;a href="https://x.com/scalix_world" rel="noopener noreferrer"&gt;X&lt;/a&gt; or come find us on &lt;a href="https://discord.gg/Ktq9qvpzBM" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>startup</category>
      <category>programming</category>
    </item>
    <item>
      <title>Remote vs Local MCP Servers, Explained</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Thu, 23 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/remote-vs-local-mcp-servers-explained-1ail</link>
      <guid>https://dev.to/scalixworld/remote-vs-local-mcp-servers-explained-1ail</guid>
      <description>&lt;p&gt;A local MCP server runs on your own machine. A remote MCP server runs somewhere always-on, at a URL, so anything you give permission can reach it. That is the whole distinction, and almost every other difference between the two follows from it.&lt;/p&gt;

&lt;p&gt;If you already know &lt;a href="https://scalix.world/blog/what-is-an-mcp-server" rel="noopener noreferrer"&gt;what an MCP server is&lt;/a&gt;, the local versus remote question is really a question about where the server lives and who gets to talk to it. Local is perfect for personal development. Remote is how you share a server with a team or put it in production. This post walks through the practical differences: transports, auth, access, and how to move from one to the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one difference that matters
&lt;/h2&gt;

&lt;p&gt;An &lt;a href="https://scalix.world/blog/what-is-an-mcp-server" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt; is a program that exposes tools and data to an AI agent over the &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;. It has to run somewhere, and that somewhere is the whole story.&lt;/p&gt;

&lt;p&gt;A local MCP server runs as a process on your laptop. The AI client you use, an editor like Cursor or a chat app like Claude, launches it directly and talks to it on the same machine. Nothing leaves your computer. When you close the laptop, the server stops.&lt;/p&gt;

&lt;p&gt;A remote MCP server, sometimes called a hosted MCP server, runs on a machine that stays on, at a stable network address. It does not care whether your laptop is awake. Any client you authorize, yours, a teammate's, or a production agent, can connect to the same URL and use the same tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transports: stdio vs streamable HTTP
&lt;/h2&gt;

&lt;p&gt;The clearest way to tell local and remote apart is the transport, the channel the client and server use to exchange messages. The Model Context Protocol defines two standard MCP server transports, and they map almost exactly onto local versus remote.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stdio&lt;/strong&gt; is the local transport. The client starts the server as a subprocess and speaks to it over standard input and output, the same pipes a normal command-line program uses. There is no network involved. It is fast, simple, and only reachable from the one machine the process runs on. This is the default for local MCP servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Streamable HTTP&lt;/strong&gt; is the remote transport. The server listens at an HTTP endpoint, and clients connect to it over the network like any other web service. It can stream responses back as they are produced, which is where the name comes from, and it is what lets a server at a URL serve many clients at once. When people talk about streamable HTTP MCP, this is the transport they mean.&lt;/p&gt;

&lt;p&gt;So stdio vs HTTP MCP is not a style choice. stdio is for a server on your machine. Streamable HTTP is for a server other machines need to reach. Choosing the transport is choosing local or remote.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a local MCP server is the right call
&lt;/h2&gt;

&lt;p&gt;Local is the correct default more often than people expect. Reach for a local MCP server when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are building or prototyping a server and want a tight edit-and-test loop.&lt;/li&gt;
&lt;li&gt;The tools touch things that only exist on your machine, like local files or a dev database.&lt;/li&gt;
&lt;li&gt;The data is sensitive and you would rather it never leave your computer.&lt;/li&gt;
&lt;li&gt;You are the only person, and the only agent, that needs it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a personal tool you use from your own editor, hosting it would add cost and moving parts for no benefit. Local wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you want a remote (hosted) MCP server
&lt;/h2&gt;

&lt;p&gt;You move to a remote MCP server the moment more than your own laptop needs to reach the tools. Common triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A teammate wants to use the same server from their own agent.&lt;/li&gt;
&lt;li&gt;A production agent, running on a server rather than your desk, depends on it.&lt;/li&gt;
&lt;li&gt;You want the tools available on a schedule or around the clock, not only when you are at your machine.&lt;/li&gt;
&lt;li&gt;Several clients or agents call it at once, and a single local process is no longer enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A hosted MCP server gives you one address that every authorized client shares, and uptime that does not depend on anyone's laptop. That is the difference between a tool you use and a tool your organization runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication changes when you go remote
&lt;/h2&gt;

&lt;p&gt;Auth is where local and remote genuinely diverge, and it is worth being deliberate about.&lt;/p&gt;

&lt;p&gt;A local server over stdio needs no network authentication. The trust boundary is your machine. If someone can start the process, they are already on your computer. Secrets like API keys are usually passed in through environment variables or the client's config, and they stay local.&lt;/p&gt;

&lt;p&gt;A remote server is reachable over the network, so it has to prove who is calling before it runs anything. Otherwise your tools are open to whoever finds the URL. The Model Context Protocol defines an authorization model for HTTP transports based on OAuth 2.1, and in practice remote servers are protected with OAuth or with bearer tokens and API keys. The rule of thumb: the instant a server leaves your machine, it needs real auth in front of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration path: local to remote
&lt;/h2&gt;

&lt;p&gt;Going from local to remote is less work than it sounds, because the server logic, the tools it exposes, does not change. What changes is how it is reached.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Switch the transport from stdio to streamable HTTP, so the server listens on a port instead of talking over stdin and stdout. Most MCP server frameworks support both, so this is often a config change rather than a rewrite.&lt;/li&gt;
&lt;li&gt;Add authentication, since the server is now exposed to the network.&lt;/li&gt;
&lt;li&gt;Run it somewhere always-on, at a stable URL, and point your clients at that address instead of launching a local process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third step, the actual hosting, is its own topic. We wrote a full walkthrough in &lt;a href="https://scalix.world/blog/how-to-host-an-mcp-server" rel="noopener noreferrer"&gt;how to host an MCP server&lt;/a&gt;, from the four things hosting requires to a deploy you can copy.&lt;/p&gt;

&lt;p&gt;Local and remote are not competitors. They are two stages of the same server. You build and test locally over stdio, and when the tool needs to be shared or run in production, you swap to streamable HTTP, add auth, and host it. If you get to that step and want somewhere to put it, &lt;a href="https://scalix.world/run" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; hosts long-running services like remote MCP servers at a stable URL any authorized agent can reach. But start local. The move to remote is easy once you need it.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>What Is an MCP Server?</title>
      <dc:creator>Scalix World</dc:creator>
      <pubDate>Wed, 22 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/scalixworld/what-is-an-mcp-server-3im3</link>
      <guid>https://dev.to/scalixworld/what-is-an-mcp-server-3im3</guid>
      <description>&lt;p&gt;An MCP server is a small program that gives an AI agent a standard way to use tools and reach data outside its own model. That is the whole idea. If you have asked what is an MCP server and gotten a wall of jargon back, here is the plain version: it is the thing that lets an assistant read a file, query a database, or call an API, instead of only writing text about them.&lt;/p&gt;

&lt;p&gt;MCP stands for the &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;, an open standard for connecting AI agents and the apps they run in to the outside world. A server is one end of that connection. The agent is on the other end. When people say "an MCP server," they mean a program that speaks this protocol and offers up a set of capabilities any MCP-capable agent can use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agents needed a standard in the first place
&lt;/h2&gt;

&lt;p&gt;A language model on its own is sealed off. It can reason about your calendar, but it cannot open it. It can describe a SQL query, but it cannot run one. To do real work, an agent has to reach systems that live outside the model: your files, your database, a payments API, a search index.&lt;/p&gt;

&lt;p&gt;Before MCP, every one of those connections was a custom job. If you had five AI apps and ten tools you wanted them to use, you were potentially building fifty separate integrations, each with its own glue code, its own auth, and its own quirks. Ten tools, five apps, fifty bespoke bridges that all break in different ways.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol collapses that. Build a tool once as an MCP server, and any MCP-capable client can use it. Build a client once, and it can talk to any MCP server. The problem goes from multiplying to adding. This is the same move USB did for hardware: one standard port instead of a drawer full of proprietary cables. The official docs describe MCP as a USB-C port for AI, and the analogy holds.&lt;/p&gt;

&lt;h2&gt;
  
  
  How MCP works: clients and servers
&lt;/h2&gt;

&lt;p&gt;MCP has two roles, a client and a server, and understanding the split is most of understanding the protocol.&lt;/p&gt;

&lt;p&gt;The server exposes capabilities. It is a program you (or someone else) writes that says "here are the things I can do" and then waits for requests. A server might wrap your company database, a GitHub account, a weather API, or a folder of documents.&lt;/p&gt;

&lt;p&gt;The client lives inside the AI application and consumes those capabilities. The application itself is usually called the host. Think of a chat app like Claude, or the Cursor editor, or a custom agent you built. The host runs a client for each server it connects to, and that client is what opens the connection, asks the server what it offers, and relays the agent's requests back and forth.&lt;/p&gt;

&lt;p&gt;So the difference between an MCP client and server is direction. The client asks; the server answers. One AI app can run many clients at once, each wired to a different server, which is how a single agent ends up with a database tool, a file tool, and a search tool all available in the same session.&lt;/p&gt;

&lt;p&gt;Under the hood they exchange structured JSON messages, so any client and any server can understand each other regardless of what language either was written in. You do not need to know the wire format to use MCP, but it is why the whole thing composes so cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an MCP server actually exposes
&lt;/h2&gt;

&lt;p&gt;When an agent connects to an MCP server, the server advertises what it offers. Most of that falls into three kinds of capability.&lt;/p&gt;

&lt;p&gt;Tools are actions the agent can take. Each tool has a name, a description, and a defined set of inputs, so the model knows when and how to call it. A &lt;code&gt;search_orders&lt;/code&gt; tool might take a customer ID and return recent orders. A &lt;code&gt;create_issue&lt;/code&gt; tool might take a title and a body and open a ticket. Tools are the part people mean most often when they talk about MCP, because they are what turn a chat assistant into something that acts.&lt;/p&gt;

&lt;p&gt;Resources are data the server makes available for context: the contents of a file, a database record, a document. The agent reads them to inform an answer, without the server performing an action.&lt;/p&gt;

&lt;p&gt;Prompts are reusable templates the server can offer. They are prewritten instructions for common tasks, so a user or an agent can trigger a known-good workflow instead of writing it from scratch.&lt;/p&gt;

&lt;p&gt;Here is a concrete example. Say you run a support team and you build an MCP server for your helpdesk. It might expose a &lt;code&gt;find_ticket&lt;/code&gt; tool, a &lt;code&gt;reply_to_ticket&lt;/code&gt; tool, a resource for your canned-response library, and a prompt that walks the agent through triaging a new ticket. Connect that server to an assistant, and the assistant can now work your helpdesk directly, in plain language, with no custom app wrapped around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local vs hosted: where the server runs
&lt;/h2&gt;

&lt;p&gt;An MCP server has to run somewhere. On your own machine it runs as a local process, and the client talks to it directly. That is perfect for personal tools and for development. It only exists while your machine is on, and only your local agent can reach it.&lt;/p&gt;

&lt;p&gt;The moment you want a teammate's agent to use the same server, or you want it available when your laptop is closed, or you want a production agent to depend on it, the server needs to be hosted: running always-on at a stable URL that any authorized client can reach. That is a separate topic with its own tradeoffs, and we cover it in detail in &lt;a href="https://scalix.world/blog/how-to-host-an-mcp-server" rel="noopener noreferrer"&gt;how to host an MCP server&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you need to build or host one?
&lt;/h2&gt;

&lt;p&gt;Most people meet MCP as users before they ever build a server. You can install existing MCP servers today and connect them to an agent you already use. You only reach for building your own when you have a tool or a data source that no existing server covers, which, for anyone with an internal system, tends to happen fairly quickly.&lt;/p&gt;

&lt;p&gt;If you do build one and want it reachable by more than the agent on your laptop, you will need somewhere to run it. That is where a platform helps: &lt;a href="https://scalix.world/run" rel="noopener noreferrer"&gt;Scalix Run&lt;/a&gt; hosts long-running services like MCP servers with a stable URL and always-on uptime, so your agent can reach your tools from anywhere. But that is the next step.&lt;/p&gt;

&lt;p&gt;For now, here is an MCP server explained without the jargon: it is how an AI agent reaches the real world, through one open standard instead of a hundred custom integrations. Learn what it is, and the rest of the ecosystem starts to make sense.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>agents</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
