Back to Explore
GuideVibeFix 编辑部Updated Oct 30, 2026

Set the Numbers First: A Practical Guide to Performance Budgets for Vibe Projects

Optimization tricks cannot save a project that never agreed how slow is too slow. This guide covers how to set a first performance budget, enforce it in CI, negotiate the four payback options when it is exceeded, and budget AI features separately, with a pre-release checklist.

A real photo of an analog stopwatch, echoing the theme of measuring time against a budget
A real photo of an analog stopwatch, echoing the theme of measuring time against a budget

The example product and person below are fictional: the example product is "Lime Ledger", a solo-built expense-tracking tool, and the example developer is Zhou Yuan. The method in this guide applies to any solo or small-team project. The numbers are illustrative reference values, not industry standards — set your own based on your users and their devices.

Many vibe projects are not slow because of technology. They are slow because nobody said in advance how slow is too slow. That was the story of Zhou Yuan's "Lime Ledger": the first version only tracked expenses and showed reports, and it opened fast. Then came a chart library, photo recognition, and shareable posters, and the home page went from just over a second to more than four seconds. Users started complaining, and one comment said opening it once took so long that they simply stopped using it. Zhou Yuan optimized — compressed images, split code — and got the home page back to just over two seconds, but the next feature pushed it up again. Only then did he see the real problem: the project had never had a performance budget. Nobody had ruled how big the home page could be or how long the first screen could take, so every feature silently accepted "a little slower", and a little slower, added up, became four seconds.

A performance budget is a line agreed in advance: under stated device and network conditions, how much resource a page may use and how long it may take. It is not a list of optimization tricks. Optimization tricks answer "how do we get faster"; a budget answers "how fast counts as good enough, and what do we do when we exceed it". Without a budget, optimization never ends and never sticks. With one, every new feature has a number to check against, and arguments change from "it feels a bit slow" to "the first-screen budget is two seconds, we are at two point six, six hundred milliseconds over — which part do we cut?"

What exactly does a budget cover?

A budget does not need to cover everything on day one. Covering the few things users feel most is enough. First is first-screen time: how long from tapping into a page until users can make sense of its content. For content and tool pages this is the number to set first, because this is when users are most likely to leave. Second is interaction response: how long after tapping a button, switching a tab, or typing a number before the interface reacts. For a tracker opened several times a day, a half-second delay on every tap feels sluggish even if the first screen was fast. Third is bundle size: how much JavaScript and styling the first screen must download. The bigger the bundle, the slower the first screen on weak networks and low-end phones, and this number creeps up unnoticed — a chart library adds hundreds of kilobytes, a date library adds tens more.

Fourth is images and media. Images are often the heaviest part of a page; a single uncompressed screenshot can outweigh several code bundles. A budget should reserve a separate allowance for images: total first-screen image weight, a per-image cap, and whether images use suitable sizes and formats. Fifth is API and AI waiting time. Many vibe projects now call AI features, and model responses taking seconds is normal. That must not be lumped together with ordinary APIs: two seconds is slow for a normal API, while five seconds for an AI generation may be acceptable — provided the interface keeps giving feedback instead of sitting blank. So write the budget in parts: one number for ordinary APIs, one for AI features, one for streaming output.

Zhou Yuan's first budget for "Lime Ledger" followed exactly these five areas, in just six lines: the home first screen, on a mid-range Android phone over throttled 4G, under two seconds; tapping "add expense" to popup in under two hundred milliseconds; first-screen JavaScript under two hundred kilobytes; first-screen images under three hundred kilobytes in total; ninety-five percent of ordinary API calls under eight hundred milliseconds; AI receipt recognition within ten seconds, with a "recognizing" state shown within one second. Six lines, each measurable and checkable before release. A budget should be lean, not long — twenty lines nobody remembers are the same as no budget at all.

How to set a first budget without guessing

The worst way to set a budget is to copy someone else's numbers. Their "two-second home page" may have been measured on a flagship phone over fiber, while your users may be on budget phones in the subway. The right order is to measure your own baseline first: take the most ordinary, even slightly old phone you have, throttle the network, open your current page, and record first-screen time, bundle size, and image weight. That measured value is your starting point, and the budget should sit slightly better than it — within reach, not on the moon. If the first screen is now three point two seconds, set two point five, not one second. Hold the line against getting worse first, then improve version by version. A budget that can never be met only teaches a team to ignore budgets.

Different kinds of projects need different emphases. For a mostly static personal homepage, first-screen time and images matter most, and interaction response can be looser. For a tracker, to-do, or check-in tool opened daily, interaction response and bundle size matter more, because half a second lost on every open adds up to real annoyance. For an image-heavy portfolio or recipe site, give images their own budget: better to show two fewer images on the first screen than to let one huge image drag the whole page down. Zhou Yuan first set one number for every page and the report page could never meet it, so he switched to one set for the home page, one for reports, one for settings. The report page, heavy with charts, got its bundle allowance raised to three hundred kilobytes, but its first-screen time budget stayed the same — the fix was loading charts on demand: numbers first, charts drawn afterwards. Budgets split by page and scenario are budgets that can actually be kept.

One more easily missed point: a budget must state its test conditions. The same page measures one second on office Wi-Fi and maybe three seconds on throttled 4G. Every budget line needs a sentence saying on what device and network it is measured, or every later argument becomes "but it is fast on my machine". Zhou Yuan's budget file states conditions on every line, for example "mid-range Android phone, throttled 4G, cold start, cache cleared". With conditions fixed, measurements are comparable, and over-or-under becomes something you can argue about with facts.

Put the budget where it can actually stop you

A budget that lives only in a document is the same as no budget. The most effective move is to make it a gate in the release process: before every change merges, run a check, and if the budget is exceeded, a red light goes on. It does not need to be fancy at first — even manually running a few commands and pasting the results into the merge description beats "everyone please remember". Zhou Yuan's approach was a performance-budget.json file in the repository holding those six numbers; before every release he ran a bundle-size check and a throttled real-device test, compared the results with the file, and if anything exceeded, the release notes had to say which item exceeded, why, and how it would be paid back. A file has three advantages: it is visible, editable, and has history — later, when someone asks who set two seconds and why, the commit history answers.

Once the routine works, automate the checks. Bundle size over budget should fail continuous integration outright, because an over-budget bundle almost always means someone quietly added a heavy dependency. First-screen and API times can start as warnings rather than failures, since network jitter makes timing measurements bounce, and blocking releases on one jittery run causes real harm. Zhou Yuan's rule: volume over budget always blocks, time over budget blocks only after two consecutive failures, and a single failure is recorded and must be handled in the next version. That keeps teeth without letting one network hiccup freeze a release. Automation exists so that "over budget" does not depend on memory or willpower.

The budget file must also answer one more question: who may change the budget. Budgets are not carved in stone. As a product grows, users change devices, and features get heavier, budgets should move too. But changing a budget must be done in the open: which line changed, from what to what, and why, written in the commit message so that even your future self can follow it. The worst case is someone quietly changing two seconds to four seconds to get a release out, with nobody noticing. Zhou Yuan's rule for himself: relaxing a budget requires its own commit with its own reason, never bundled into a feature commit. That one rule stopped several "relax it now, fix it later" impulses.

Over budget? Four ways to pay it back, in order

A budget earns its keep not on the day it is set, but on the day it is first exceeded. Zhou Yuan's first breach came with a share-poster feature: the drawing library it needed pushed first-screen bundle size from one hundred ninety to two hundred sixty kilobytes, sixty over budget. The common first reaction is "let's just relax the budget to three hundred, it's only this once" — but "only this once", repeated a few times, leaves the budget meaningless. He later settled on four ways to pay back, tried in this order. First, cut the feature's scope: ask whether the new feature really needs to load on the first screen at all — the poster library could load only when the user taps "share", leaving first-screen size untouched. Second, change the approach: look for a lighter library, or a built-in capability instead, for example a few small date functions instead of a whole date library. Third, load in stages: defer what is not urgent to idle time or to the moment of interaction, and give users the core content first. Fourth, and only fourth, relax the budget — and relaxing must come with a statement of cost: relaxed to what, which users it affects, and in which version it will be paid back.

The order matters: the first three solve the problem inside the budget, the fourth admits the budget must move. Reverse the order — relax first, think later — and the budget quickly becomes a rubber band. Zhou Yuan also added a negotiation template: any breach must answer four questions — which item exceeded, by how much, which users and scenarios are affected, and what users lose if nothing changes. For the poster feature the answers were: first-screen bundle size, sixty kilobytes over, weak-network users waiting roughly half a second longer on the first screen, and no effect on the core expense flow. Once answered, the decision was obvious: load the drawing library on tap, keep the first-screen budget unchanged. The template moves arguments from "is this feature important" to "how much longer will users wait, and is it worth it" — and the latter can be measured.

There is another kind of breach that is easy to miss: not one big jump, but a little growth every time. Ten kilobytes per version becomes one hundred over ten versions, and nobody feels responsible. The defense is a "growth red line" inside the budget: for example, any single change growing first-screen size by more than twenty kilobytes must be explained in its description, and three consecutive growing versions — even if none breaches the total — trigger a review. That is how Zhou Yuan's report page was saved: three versions each grew slightly, and by the end of the third only ten kilobytes of headroom remained, so he switched charts to on-demand loading early instead of scrambling on breach day. A budget should watch the trend, not just the breach.

AI features need their own budget

For projects with AI features, the AI part is where budgets most easily lose control. Model calls are slow and unstable by nature: the same prompt takes three seconds today and eight tomorrow, and backend queues, rate limits, and retries push times up and down. If you hold AI responses to an ordinary API's eight hundred milliseconds, you will breach every day, be forced to relax constantly, and end up with a dead budget. The right approach splits the AI budget into three segments. First, "how fast is feedback": after the user acts, how long until the interface shows a state like "generating" or "recognizing" — this should be short, ideally under one second, because users need to know immediately that the request was received. Second, "how fast is the first token or first batch of results": for streaming output especially, set this number, because watching words appear greatly reduces the feeling of waiting. Third is "how fast is the complete result": this can be ten seconds or more, but it must come with progress feedback and a cancel button so users can always walk away.

AI features also carry two hidden costs that belong in the budget. One is extra downloads and waiting from third-party scripts and model services, such as SDKs or model files for speech recognition and image generation — do not count only your own code bundle. The other is the cost of failure and retry: models occasionally time out or return empty results, so the budget should allow time for one retry and define the interface state for it, rather than assuming every call succeeds first time. Zhou Yuan's AI receipt recognition was budgeted in three segments: a state within one second of tapping recognize, streaming backfill of amount and category starting within three seconds, and a complete result within ten seconds, with "try again" and "enter manually" offered on timeout. Budgeted to this granularity, AI features stop being a lawless zone justified by "AI is just slow".

One more note: AI-generated images, audio, and long text also have size and load time that belong in the budget. Dropping a large generated image straight onto the first screen wipes out all the bundle savings made earlier. Zhou Yuan's rule: AI images are compressed to display size before reaching the first screen, with the original loaded only when the user opens the detail view; long text shows a summary or first lines first, with the full text on demand. The principle has not changed in the AI era: give users something usable first, and push the heavy, slow, and expensive parts later.

The five most common traps

The first trap is measuring on your own machine. A developer machine is top-spec and office Wi-Fi is fast, so numbers measured there are far better than what real users get, and budgets set from them are over-optimistic. Fix it by fixing one "worst acceptable device" as your yardstick — even a three-year-old phone lying around — and set the budget against it. The second trap is looking only at averages. An average first screen of two seconds can hide ninety percent of users at one and a half seconds and ten percent at six seconds; the average buries the worst-off users. Budgets should use percentiles — at least the ninetieth percentile, and the ninety-fifth when you can. The third trap is writing the budget into a document and calling it done, with no check in the release process; three months later nobody remembers the numbers. A budget must live in a file, in checks, and in release notes — miss one link and it slides.

The fourth trap is setting a budget only for launch day and never revisiting it. Products grow, so budgets need regular review: every month or every few versions, spend half an hour on the trend — is a page constantly pressing against its ceiling, is some page permanently at its limit? A page running at its limit will breach on the next feature, so handle it early. The fifth trap is using the budget as a punishment tool, blaming whoever breaches it. A budget exists to give trade-offs a basis, not to scare people away from adding features. Zhou Yuan's experience: breach discussions cover only numbers and user impact, never blame, and relaxing a budget is not shameful as long as the reason is written down, the cost is stated, and a payback version is set. A budget should make people brave enough to decide, not afraid to decide.

Pre-release checklist

Before a release, run through this list — it beats remembering on the spot. First, is the budget file in the repository, with test conditions on every line? Second, do you have measured data for all six areas — first screen, interaction, bundle, images, APIs, AI — not gut feeling? Third, has every breach been handled through the four payback options, with relaxations carrying reasons and payback versions? Fourth, have you tested on weak networks and old devices — office Wi-Fi alone does not count? Fifth, have you looked at the trend, and handled pages that keep growing before they breach? Sixth, do failure and timeout states have budgets too — for example, how fast the interface reports an API timeout, and whether AI timeouts offer a manual way out? If all six pass, this release's performance has been accounted for.

One honest closing note: a performance budget will not turn your project into a benchmark champion, and that is not its job. Its job is to give you an agreed line between "add the feature" and "protect the experience" before the impulse to add wins. Solo projects rarely lack optimization tricks; what they lack is someone holding up a line when the impulse arrives and saying "this slow is where we pause". That line does not need to be grand: six numbers, one file, one release check. Set it, run two versions, adjust from real measurements, and it will get more accurate with use. Without a budget, every optimization is firefighting, every feature is a gamble, and after winning a few gambles, you will eventually lose one to users' patience.

Views 0Comments 0

Comments (0)

ME
0/1000
Loading comments...
Browse projectsPublish your project

Related articles

A real photo of a person writing notes in a notebook beside a laptop at a desk, echoing the theme of leaving notes for your future self
Guide
Pick It Up After Three Months: A Continuity Handbook for Solo Projects

Solo projects rarely die because they cannot be built. They die because, once put down, they cannot be picked up again. This guide covers the five-part continuity handbook, how to write for a forgetful future self, resuming AI-assisted work, and the day-one restart order.

Developer WorkflowIndie DevelopmentLearning & Career
A real photo of books being organized on library shelves, echoing the theme of sorting tags and categories
Guide
Tags Getting Messier? A Practical Guide to Tagging and Taxonomy for Vibe Projects

Tags, categories and collections each do a different job, hierarchies should stay flat, and naming rules must come before tagging. This guide covers how to design a tag system, clean it up, decide who may create tags, and why AI tagging still needs human review, with a launch checklist.

Developer WorkflowDesign ExperienceIndie Development