<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>Udhyam Labs AI blog</title>
  <link>https://udhyamlabs.tech/blog</link>
  <atom:link href="https://udhyamlabs.tech/feed.xml" rel="self" type="application/rss+xml"/>
  <description>Engineering notes on migration, delivery, AI inference and GPU sizing.</description>
  <language>en-gb</language>
  <lastBuildDate>Tue, 06 Oct 2026 06:00:00 +0000</lastBuildDate>
  <item>
    <title>Why cloud to cloud migrations stall on stateful services</title>
    <link>https://udhyamlabs.tech/blog/why-cloud-to-cloud-migrations-stall-on-stateful-services</link>
    <guid isPermaLink="true">https://udhyamlabs.tech/blog/why-cloud-to-cloud-migrations-stall-on-stateful-services</guid>
    <pubDate>Tue, 06 Oct 2026 06:00:00 +0000</pubDate>
    <category>Cloud to cloud migration</category>
    <description>Stateless services move between clouds with a traffic change. Stateful services need a data operation. How to plan the waves around the point of no return.</description>
    <content:encoded><![CDATA[<p>A migration plan that counts virtual machines moves quickly at first. The stateless services go across, the dashboard shows steady progress, and then the programme slows down on the services that hold data or depend on something the plan did not count.</p>
<p>Those services are usually the ones that depend on identity, managed databases, key management, private circuits to partners, and partner allowlists tied to fixed addresses. They are also the ones that set the order of the whole move, so they have to be planned first.</p>
<h2 id="build-the-dependency-map-from-traffic">Build the dependency map from traffic</h2>
<p>The architecture diagram is rarely current. The map that a migration needs is built from what the estate is observed to do: network flow logs, load balancer logs, DNS query logs, the provider's API audit log and distributed traces.</p>
<p>The observation has to cover a month end and the batch cycles, because some dependencies appear only then. Where the logs you already keep cover those periods, the history can be read. Where they do not, the plan should state which cycles were not observed.</p>
<h2 id="classify-before-drawing-the-waves">Classify before drawing the waves</h2>
<p>Each workload is classified as re-host, re-platform, re-architect, replace, retire or retain, according to what it depends on. The workloads that will cost more than the plan assumed are classified first, because they decide the order of the waves.</p>
<p>One rule saves a great deal of trouble: a service and the datastore it writes to move in the same wave. Where that is not possible, count the round trips between the two providers for each request, and the data egress they generate, before the wave is drawn. The wave plan should state the response time that the split adds.</p>
<h2 id="stateless-services-a-traffic-change-that-can-be-undone">Stateless services: a traffic change that can be undone</h2>
<p>For a stateless service the move is a change to where traffic goes. DNS answers are divided by weight between a source record and a target record, so traffic follows the weights approximately. The service is returned by setting the target weight to zero.</p>
<p>The return is not instant. Cached answers and open connections drain over the record lifetime and the connection lifetime. A rollback test should measure that drain time, so that the figure in the runbook is one that has been observed.</p>
<h2 id="stateful-services-a-data-operation-with-a-point-of-no-return">Stateful services: a data operation with a point of no return</h2>
<p>A stateful service is different, because once it has taken writes on the target, returning it to the source is a data operation and no longer a traffic change.</p>
<p>While the service replicates to the target, the source stays the only writer. At cutover the sequence is:</p>
<ol><li>Stop writes.</li><li>Wait until the target has applied the source's final position.</li><li>Recheck the chunks that changed since the last full parity run.</li><li>Start the reverse stream from that position.</li><li>Move write authority to the target in one step.</li></ol>
<p>The order of the last two steps matters. If the target takes a write before the reverse stream is in place, that write is lost to any rollback.</p>
<p>Until sign-off, the service can be returned to the source by the same procedure in the other direction. At sign-off the reverse stream is removed, and from then the service can only be corrected forwards. Where the target database engine differs from the source engine and no tested reverse mapping exists, the point of no return is the cutover itself. The wave plan should say so in plain words, with the name of the person who signs it.</p>
<h2 id="count-the-cost-of-running-two-estates">Count the cost of running two estates</h2>
<p>A migration has its own cost, separate from the cost of either cloud. It includes the cost of running both estates in parallel for each wave, the data egress, and any committed spend that remains on the source.</p>
<p>A cost model for the move should give the month, if there is one, in which total spend falls below what you pay today. A plan without that month risks stopping halfway, with two estates to pay for.</p>
<h2 id="what-we-would-check-first">What we would check first</h2>
<p>If a migration has stalled part way, three questions usually show why:</p>
<ul><li>Which services write to a managed database, and which of those have a tested way back?</li><li>Which dependencies were found only at a month end or in a batch cycle?</li><li>What does each remaining wave cost in parallel running, and who has agreed to that cost?</li></ul>
<p>Our <a href="/services/cloud-to-cloud-migration">cloud to cloud migration</a> practice starts with an assessment of a named slice of the estate and produces the dependency map, the classification and the wave plan for that slice. The checks we use to show that a move is safe to continue are set out under <a href="/technology#parity">how we verify a move</a>.</p>]]></content:encoded>
  </item>
  <item>
    <title>Six questions before a proof of concept goes to production</title>
    <link>https://udhyamlabs.tech/blog/six-questions-before-a-proof-of-concept-goes-to-production</link>
    <guid isPermaLink="true">https://udhyamlabs.tech/blog/six-questions-before-a-proof-of-concept-goes-to-production</guid>
    <pubDate>Tue, 06 Oct 2026 06:00:00 +0000</pubDate>
    <category>AI inference systems</category>
    <description>A proof of concept shows that a model can do the job on a chosen sample. These are the six questions production asks next, and what to check first for each.</description>
    <content:encoded><![CDATA[<p>An AI proof of concept that works is a good result, and it is a narrower result than it looks. It shows that the technology can do the job on a sample that was chosen for it, for a few users, usually with wide permissions and nobody on call. That is appropriate for a test.</p>
<p>Production then asks six further questions. A team that answers them before the build starts knows what the build is. A team that meets them one at a time, after a launch date has been promised, usually finds the costly ones last, when they cost the most to fix.</p>
<h2 id="1-is-it-right-on-your-real-data">1. Is it right on your real data?</h2>
<p>A proof of concept is judged on a sample, and the sample is rarely the real distribution of cases. Accuracy has to be measured on cases drawn from your own work, with a correct answer agreed for each case before the test starts. The system also has to read that data from the systems of record that hold it, which is often harder than the model.</p>
<p><strong>Check first:</strong> ask two people in the business to mark the same few dozen real cases. If they cannot agree on the right answers, accuracy cannot be measured yet, and that is the first piece of work.</p>
<h2 id="2-does-it-hold-at-peak-load-and-what-does-it-cost-there">2. Does it hold at peak load, and what does it cost there?</h2>
<p>Response time has to be measured at the concurrency you expect at peak, with the mix of requests you expect, and then beyond that point until it degrades, so that the margin is known. A test with one user at a time shows neither figure.</p>
<p>Cost follows from the same test. The cost of each type of request is measured at that load, and the monthly cost is calculated from it and from the volume you expect. Where the model runs on capacity you rent or own, the cost of a request depends on how fully that capacity is used. Where the model is priced for each token, the unit price is known from the first request, and what has to be established is the volume, the supplier's rate limits and the licence terms at that volume.</p>
<p><strong>Check first:</strong> write down the peak concurrency and the response time the use case needs. Without those two numbers no sizing is possible.</p>
<h2 id="3-who-and-what-can-reach-it-and-what-can-it-reach">3. Who and what can reach it, and what can it reach?</h2>
<p>A test is often run with wide permissions. Production needs an answer for each component: who and what can reach it, what it is permitted to reach and do, what data it handles and stores, where its secrets are held, and what leaves your environment.</p>
<p>For a model there is one more question, which is what untrusted input reaches it. Text inside a document or a request can be treated by the model as an instruction, so a model that can call tools needs its permissions drawn as narrowly as any other service account.</p>
<p><strong>Check first:</strong> list every outside service the proof of concept sends data to, and confirm that each one has been approved to receive it.</p>
<h2 id="4-what-can-you-show-an-auditor">4. What can you show an auditor?</h2>
<p>An auditor asks what the system did, on which data, and who approved each change. The first two come from logs that the system has to be built to keep, with a retention period and protection from alteration that you specify. The third comes from your own change approval, which every change should pass through.</p>
<p>Both have to be designed in from the start, because neither can be reconstructed afterwards. A log added after an incident does not describe the incident.</p>
<p><strong>Check first:</strong> ask your auditors or your risk team what they would want to see for this system, before the design is drawn.</p>
<h2 id="5-how-does-it-fail">5. How does it fail?</h2>
<p>Any component can fail. Production needs to know, for each failure that can be foreseen, its cause, its effect, how it is detected and how the system recovers. A recovery time is a target until the recovery has been rehearsed, and it is a measurement afterwards.</p>
<p>For an AI system the failure that matters most leaves every health check green. A wrong answer is a failure, and so is an answer that changes after the supplier updates the model. The evaluation cases from the first question are how that failure is detected, so they have to be run again whenever the model or its supplier changes.</p>
<p><strong>Check first:</strong> pick the one failure that would cost the most, and ask how anyone would find out that it had happened.</p>
<h2 id="6-who-owns-it-and-who-runs-it">6. Who owns it and who runs it?</h2>
<p>The team that built the proof of concept is usually not the team that will run it. Your own engineers have to be able to release it, roll it back and operate it, and someone has to be on call. A named owner in the business has to accept it. In a regulated business your risk and compliance functions also have to approve it, and that approval is often the longest item in the plan.</p>
<p><strong>Check first:</strong> name the owner and the operating team now. A system with neither tends to stay a proof of concept.</p>
<h2 id="what-to-do-this-week">What to do this week</h2>
<p>The <a href="/readiness-check">readiness check</a> asks these six questions about your own proof of concept and lists what is open. It takes about two minutes, and nothing is stored.</p>
<p>If several of the six are open, that is normal, and it is the work our <a href="/services/ai-inference-systems">AI inference systems</a> practice exists to do. The <a href="/why">Why Udhyam</a> page sets out how we take a proof of concept through each question and put the answers in writing.</p>]]></content:encoded>
  </item>
  <item>
    <title>How to check a GPU quotation before you sign it</title>
    <link>https://udhyamlabs.tech/blog/how-to-check-a-gpu-quotation-before-you-sign-it</link>
    <guid isPermaLink="true">https://udhyamlabs.tech/blog/how-to-check-a-gpu-quotation-before-you-sign-it</guid>
    <pubDate>Tue, 06 Oct 2026 06:00:00 +0000</pubDate>
    <category>AI hardware advisory</category>
    <description>A GPU quotation should be sized from your workload and not from a catalogue. How to find the hardware limit that binds, and how to compare buying with renting.</description>
    <content:encoded><![CDATA[<p>A quotation for GPU servers arrives with a part list and a validity date. The part list answers the question the supplier was asked. Whether it answers the question your business has depends on four things that the quotation does not contain: the model you intend to run, the length of the requests, the number of users at peak, and the response time the use case needs.</p>
<p>This article sets out how we would check a quotation, in the order we would do it.</p>
<h2 id="start-from-the-workload">Start from the workload</h2>
<p>Sizing starts from what will run on the hardware. Before looking at the part list, write down:</p>
<ul><li>the model, its parameter count and its numeric precision</li><li>the distribution of context lengths, which is how long the requests are</li><li>the ratio of input tokens to output tokens</li><li>the arrival rate at peak</li><li>the response time target</li></ul>
<p>The last item is the one most often missing. Without a response time target there is no way to choose how many requests the server processes together, and without that there is no way to say which limit of the hardware is reached first.</p>
<h2 id="find-the-limit-that-binds">Find the limit that binds</h2>
<p>A GPU server has several limits. It can calculate only so fast, it can move data through its memory only so fast, and it holds only so much memory. The limit that your workload reaches first is called the binding constraint, and it is the one to buy against.</p>
<p>Which limit binds depends on the workload:</p>
<ul><li>At low batch width, the decode stage of a language model is limited by memory bandwidth.</li><li>As batch width rises, the limit moves towards compute.</li><li>For long contexts, the memory taken by the KV cache usually caps the batch width first. The KV cache is the stored attention state for every token already processed.</li><li>Multi-node training is frequently limited by the network between the nodes.</li></ul>
<p>This matters for the comparison between two parts. When memory bandwidth is the limit, a part with a higher compute figure and the same bandwidth adds almost no throughput at that operating point. A quotation built on the headline compute figure can therefore be the wrong purchase for a serving workload.</p>
<p>The way to find the binding limit is to measure. We run a representative workload on rented capacity of the same accelerator, in an account you control. That measurement characterises the accelerator. The quoted host and network are then checked by calculation, and the findings say which figures were measured and which were calculated.</p>
<h2 id="check-what-surrounds-the-accelerator">Check what surrounds the accelerator</h2>
<p>The host, the network, and the power and cooling envelope are decided together with the accelerator. A quotation can be correct on the accelerator and still not be something your facility can run. These are the questions to put to the supplier in writing:</p>
<ol><li>What power does one fully loaded server draw, and what does a full rack need?</li><li>What cooling must the data centre supply for that rack?</li><li>Is the network sized for serving or for multi-node training? The two need different designs.</li><li>What does the support contract cover, and for how long?</li></ol>
<h2 id="put-buying-colocating-and-renting-on-one-basis">Put buying, colocating and renting on one basis</h2>
<p>The three routes are priced in different units, so they have to be converted to one. The unit that works is the cost per million tokens, because it is the unit that suppliers of rented capacity price in.</p>
<p>For hardware you own, the figure is built like this:</p>
<blockquote><p>The capital cost depreciated over a stated period, plus financing, power, space, support contracts and the staff to run the hardware, divided by the tokens served at the utilisation you expect.</p></blockquote>
<p>Dividing by the tokens served at the utilisation you expect is how idle capacity enters the figure. Servers that stand idle for half the day cost close to twice as much for each token as the same servers kept busy, because the fixed costs are spread over half the tokens.</p>
<div class="table-scroll"><table><thead><tr><th>Route</th><th>What you pay for</th><th>What moves the answer most</th></tr></thead><tbody><tr><td>Buy and house it yourself</td><td>Capital, financing, power, space, support and staff</td><td>How fully the servers are used</td></tr><tr><td>Buy and colocate</td><td>Capital, financing, the colocation fee, support and staff</td><td>Utilisation, and the length of the contract</td></tr><tr><td>Rent</td><td>A price for each hour or for each token</td><td>How steady the demand is</td></tr></tbody></table></div>
<p>Suppliers price input tokens and output tokens separately, so the figure should be given for each, or as one figure at your measured mix.</p>
<p>Before committing capital it can be cheaper to rent the same capacity for a period, observe how heavily it is used, and buy only if use stays high. The useful output of the exercise is the level of sustained use at which buying becomes cheaper than renting for your workload.</p>
<h2 id="before-the-validity-date">Before the validity date</h2>
<p>A quotation check has four possible answers: buy as quoted, buy less or more, buy a different part, or rent first. Any of the four is a good result if the arithmetic behind it is shown.</p>
<p>If you hold a quotation now, the two things that decide whether a check is possible are the validity date and a description of what you intend to run. Our <a href="/services/ai-hardware-advisory">AI hardware advisory</a> practice does this work, and no supplier pays us, whichever answer we give. The method is set out in more detail under <a href="/technology#sizing">how we size compute</a>.</p>]]></content:encoded>
  </item>
</channel>
</rss>
