Whatever you pick, check the renewal terms on the domain too. Some hosts bundle a free domain and then charge $25 to renew it, and getting the transfer auth code out of them is deliberately tedious.
Ora
@adjunct_ora
Teaches four courses across two colleges and tracks every hour of it in a spreadsheet.
54 credit Contributor
- From answers
- 0
- From questions
- 54
Also check the band is a standard width. Cheap trackers usually die at the strap long before the electronics give up.
Also look at how much tool output you are stuffing back in. Three steps of full file contents can be 20k tokens and it pushes the instruction out of the region the model is paying attention to. Truncate tool results to what the next decision needs - a diff summary rather than the whole file, 20 rows rather than 2,000 - and the drift gets noticeably better on its own.
Gently disagreeing with heavy from the start, which is where the popular advice goes. Coming from nothing at 48, muscle adapts in weeks and tendons and connective tissue adapt over months, so the first eight weeks want to be about technique and consistency with loads that feel almost too easy. I skipped that and got a very sore elbow that cost me more time than the eight weeks would have. Heavy is the destination, not the starting position.
You have already found it - 980ms of ORM start-up and 410ms of connect are 50% of your cold path and neither is your code. Three things in order of payoff:
- Stop opening a TCP connection per cold instance. Use a driver that talks to the database over HTTP or a WebSocket through a pooler rather than a raw socket. That 410ms is DNS plus a TLS handshake plus the Postgres startup exchange, and over HTTP it collapses to one round trip you were paying anyway. On our worst route it went 410ms -> 90ms.
- Check what the 480ms of require is actually loading. Run the build with the bundle analyser and look at the server chunk for that route. Ours was pulling a date library, an entire SDK and a logger with 40 transports because one utility file re-exported everything from an index barrel. Deleting the barrel took 480ms to 150ms.
- Then reconsider the ORM on that route. A hand-written query through a thin driver has effectively no start-up cost. You do not need to rip it out everywhere - one hot route is enough.
What you cannot fix is the 620ms of runtime init. That one you buy your way out of with minimum instances if the platform offers it.
That is the usual number. Barrel files are fine in application code and quietly expensive on any boundary where the module graph gets loaded from scratch - which is exactly what a cold start is.
The loop is doing exactly what you built. Nothing in the transcript tells the model it already tried that query, and nothing tells it the results were bad - a tool that returns three irrelevant chunks with status: ok looks identical to a tool that worked. So it rephrases and tries again, forever, which is what a person would do if every attempt came back looking plausible.
Four changes, cheapest first:
- Dedupe at the tool boundary. Hash the arguments, and on a repeat return
already called at step 4, result was unchangedinstead of running the search again. Costs nothing and kills nine of your 38 immediately. - Make failure legible. Return the retrieval scores and say so:
3 results, top score 0.31, below threshold 0.6. A model that can see it is failing will stop; a model that cannot, will not. - Give it a way out. Add an explicit
answer_with_gapsorescalate_to_humantool and say in the system prompt that using it after two failed searches is the correct behaviour. Without a legitimate exit, the only action available is another search. - Cap consecutive identical-tool calls at 3 in the loop itself, not in the prompt.
The real fix underneath all of that is retrieval. If step 1 had returned the refund policy, none of this happens.
They are the single most useful token in that payload. The model has no other way to distinguish "found nothing" from "found something irrelevant", and those two situations want completely different next moves.
Going to push back on the top answer a little. Yes it accommodates you, but below B2 the binding constraint for most adults isn't accuracy, it's total minutes of speech ever produced. Plenty of people who've studied for three years have spoken for maybe four hours cumulatively. A partner who never judges you gets that number up by an order of magnitude, and volume fixes an embarrassing amount on its own. The correction loop you're missing is cheap: record yourself, listen back the next day, write down the three things that made you wince.
Wrote back with a range last spring, got an offer at the bottom of it, and then successfully moved it up by about six percent by pointing at a specific responsibility in the job description that had not been in the screening conversation. Writing the range early did not cost me the later negotiation, which is the thing I had been afraid of.
If you're carrying camera gear none of this applies and the maths changes completely. Two bodies and three lenses is a 30L problem before you've packed a single shirt.
It is the most common misreading of warming, and it is understandable because it does fix the demo you run yourself at 08:55. One request from you finds the warm instance; eleven simultaneous requests do not.
The ping keeps one instance warm. Your traffic is bursty, so at 09:02 when eleven people arrive at once the platform spins up ten more instances and ten of those requests eat the full 1.4s anyway. You will have paid for 4,000 extra invocations a month to fix the experience of exactly one user, which admittedly is the one who complains.
For 1,400 requests a day the container is the honest answer. It is $7, there is no cold start to reason about, and you can stop thinking about this permanently. Warming tricks earn their keep when traffic is high enough that a warm pool actually absorbs the burst, and yours is not.
Second the descriptions point, and add: name them so a stranger could sort them into piles. warehouse_run_query and tickets_search beat run_query and search by a distance, because the prefix carries domain information into every mention of the tool in the transcript, not just into the definition block.
Costs you nothing, no architecture, and it shows up immediately in the wrong-tool rate.
My bank matched too, and only after I had a signed competing commitment in hand rather than a verbal quote. They will not move on "someone told me they could do better".
Coerce, but count. If you silently normalise you lose the only signal that tells you the schema is confusing, and six months later nobody knows whether it is 1 in 6 or 1 in 600. Increment a metric in the preprocess branch and you get the ergonomics and the visibility.
If your provider supports a strict or constrained decoding mode for tool arguments, turn it on and this class of bug largely stops existing, because the sampler cannot emit a string where the grammar demands an array. The catch is that strict modes usually support a subset of JSON Schema - no $ref, limited unions, sometimes every property required - so you may end up making the same simplifications anyway. Which is the actual lesson: the schema shapes that models handle well and the ones constrained decoding supports are almost the same list.
I am going to disagree with everyone recommending alterations. If every single button down you own does this, you are paying a tailor to correct a garment that was never drafted for your body, and you will pay again on the next shirt and the one after. I stopped buying menswear-cut shirts entirely and switched to knit tops with collars and to shirts with a bit of stretch and princess seams for client days. Nobody has ever commented, my mornings got simpler, and I stopped budgeting for alterations altogether.
This matches what I see teaching adults. In the first six months the fifty-year-olds usually outperform the teenagers badly, because they already know what a subjunctive is and they actually do the homework. The gap the research talks about shows up much later and mostly in places you said you don't care about.
connection_limit=1 took the error rate from 15% to zero in the same load test. I had read that parameter three times and assumed it was a maximum I would never reach.
pg_stat_activity showed 22 rows with an application_name I did not recognise, which turned out to be the ORM's introspection running on every deploy. Not the main bug but definitely a contributor during deploy windows.
The freezer works and I have done it for years, but only if you are disciplined. Portion into small airtight bags with as little air as possible, and when you take one out let it come to room temperature while still sealed before opening. Open a cold bag in a warm kitchen and moisture condenses onto the leaf, which is worse than doing nothing. Never refreeze one you have opened. Done properly I have opened a bag a year later that was recognisably the tea I bought.
That is a reasonable line to draw. I would only bother freezing something genuinely special that I cannot rebuy.
Teaching four sections while finishing is not neutral, it is actively negative. I taught three in my last year and lost every morning to grading guilt. If you stay, negotiate down to two sections and see whether the department blinks.
Explaining to an actual person beats explaining to a notebook or a rubber duck, because a person asks the question you skipped. I run this with students in pairs: eight minutes to explain one topic, and the listener's only job is to ask 'why' twice and 'what would happen if that weren't true' once. The three questions are always the ones the explainer had quietly avoided. It's also much harder to bluff out loud than on paper, which is precisely the value.