Last updated 2 September 2026
Kodukeel is free to use, there is nothing to buy, and nothing about you is sold. This page is the arithmetic behind that sentence: what the app runs on, what each piece costs, who is paying for the copy you are reading, and what would change if somebody funded it.
This installation is run by Upthink Solutions OÜ, and they pay the bills on this page. Kodukeel is software somebody installs rather than one service, so every copy has its own operator and its own invoice.
The code is MIT licensed and the dictionary data is not ours to license: Ekilex is CC BY 4.0 and Wiktionary is CC BY-SA 4.0, which is share-alike and therefore reaches the built dictionary as well. Anyone may run their own copy, and at one learner it costs the price of a domain name.
11 things, and every one of them has a price on it. The list is longer than the one on the privacy page, because that page answers a narrower question: a service can hold every row in the database without ever being told who a learner is.
Nothing anybody bills us for is counted as free. Every vendor here is on the plan a real deployment is on, because a free tier is one that pauses when nobody is on it or forbids commercial use, and modeling one would describe a deployment nobody runs.
What is given is credited, not priced. Ekilex, Wiktionary and TartuNLP are public institutions that decided this work should be available. They ask for nothing, and that is a good arrangement rather than a gap in the accounts, so they are named here with what each one gives and the license it comes under, and they appear in no total. Where buying the same thing is possible the panel says what that would come to, because the size of the gift is worth seeing. The last line of each card is the one worth reading: every entry is a state the app already handles rather than a disaster.
Vercel, in the same region as the database
Runs the app: every page rendered, every action answered, the speech proxy and the tutor route.
Without it: The pages a phone has already seen still open, and nothing new loads.
Supabase, holding the database, the sign-ins and the cached speech
Every deck, every review, the dictionary, who is signed in, and the speech files keyed by their content.
Without it: Nothing works, and the landing page falls back to a dictionary of five words.
OpenRouter, Anthropic, OpenAI, Groq or Google, whichever has a key
Anu, the note on a piece of writing, and reading a photographed page. Never a single Estonian form.
Without it: Anu says she cannot reach anybody. Review, the dictionary and every drill are untouched.
TartuNLP, at the University of Tartu
Reads a word or a sentence aloud in any of ten voices. Every clip is cached and asked for once.
Without it: Cards are silent, and the listening part of the mock exam says so rather than failing.
The Institute of the Estonian Language, and the Wikimedia Foundation
Every Estonian form and example sentence, and the English meaning of most of the dictionary.
Without it: Live lookups stop. The seeded dictionary carries on, and a word it lacks is simply missing.
Resend, sending the mailed sign-in links
Sends a sign-in link to anybody without a Google account, and the occasional reminder.
Without it: Google sign-in still works. Everybody else is locked out.
Sentry, or whatever the deployment points its webhook at
Catches anything that breaks, redacted, with a user id and never an email address.
Without it: Errors are in the server log and nowhere else, which is where they were before.
Anthropic, as the tooling that writes and maintains this
Writes the code, the tests and the invariants, and keeps them honest against each other.
Without it: The app carries on running and stops being worked on.
A registrar, under the Estonian Internet Foundation
The address people type. The cheapest line here by a long way.
Without it: The app is still there under whatever address the host gave it.
Whichever public feed the deployment points at
Suggests words off today's front page, and prints a few headlines the dictionary can open.
Without it: The suggestion row draws from the season or at random instead, and says which.
Them
Keeps 400 clips, 60 pages and every grade that could not be sent, so review works on a train.
Without it: There is no app. This is the one piece of the infrastructure nobody here can pay for.
On this installation. Sign-in is on, so every learner has a deck of their own. Live dictionary lookups are off, so the built-in dictionary answers by itself, and speech is cached in shared storage. Anu is answered by OpenRouter, Groq and Google Gemini, on models that are given away at the tier this uses, which the panel below still prices as though they were bought.
Move the slider. Nothing here is stored and nothing is sent anywhere; the arithmetic runs in your browser, out of the same modules the app itself uses to decide when to stop spending.
Every month, all of it
$322.65
$3.23 a learner, and every cent of it an invoice somebody sends. In US dollars and net of VAT, which is how the vendors quote their own prices.
Not counted above: buying the speech this app is given would come to a further $2.88 a month. Nobody has ever asked for it.
How hard they study
Cards read themselves aloud
The tutor
Which model answers
Years of reviews already stored
Pro
The Pro plan's own fee. Nothing here is over its allowance yet.
Requests answered52,823 of 1,000,000 included
Files served209,243 of 10,000,000 included
Data out621 MB of 1,000 GB included
Processor time35 min of 4 hours included
Pro, Micro
The Pro plan's own fee, with the smallest instance inside its compute credit.
Database177 MB of 8 GB included
Data out632 MB of 250 GB included
Speech stored759 MB of 100 GB included
People signing in100 of 100,000 included
Opus
A question and a writing note on Opus, priced the way the ledger prices one before it makes the call.
Public, and asks for nothing
180,000 characters read aloud a month, in a real Estonian voice, which would come to $2.88 a month to buy.
A public research group at the University of Tartu, which asks for nothing and sends no invoice.
Public, and asks for nothing · Ekilex under CC BY 4.0, Wiktionary under CC BY-SA 4.0
6,110 checked entries with 39,421 forms, and the attested sentences every exercise is built from.
Neither asks for anything, and neither has a price to quote: nothing else holds a checked Estonian case table with attested sentences, so there is nothing to compare it against.
Pro
The Pro plan. The free tier sends a hundred a day from a shared address, which is for testing.
Emails sent300 of 50,000 included
Team
A flat plan. It bills by volume of errors rather than by learners, and a well-behaved month is nowhere near the allowance.
Claude Max, 20x
The only line here that is not runtime. It does not move with the number of learners, so it is most of the bill at a hundred and a rounding error at a hundred thousand.
One a year
A .ee domain. The registry charges 6 euros a year; a registrar asks about 15.
No bill of its own
One request an hour from a function we already pay for, cached and shared by everybody.
Not the operator's to pay
Their hardware, their battery and their data. Every clip and page it keeps is one this deployment does not serve again.
Each bar is ten times the learners of the one before it, and the heights are logarithmic, so a bar twice as tall is a bill many times larger. The shape to look at is the steps.
| Learners | A month | Given | Each |
|---|---|---|---|
| 1 | $301.07 | $0.03 | $301.07 |
| 10 | $303.03 | $0.29 | $30.30 |
| 100 | $322.65 | $2.88 | $3.23 |
| 1,000 | $519.09 | $28.80 | 52 cents |
| 10,000 | $946.94 | $288.00 | 9.5 cents |
| 100,000 | $2,641 | $2,880 | 2.6 cents |
The floor is the interesting end. The plans, the tooling, the mail and the domain come to about three hundred dollars a month before a single learner arrives, and most of that does not move when they do: the first thousand people are nearly free to serve, and the cost per head falls by roughly a factor of ten for each decade. What grows instead is speech and the database, so past ten thousand the shape is set by how much is said aloud and how many years of reviews are being kept.
Everything else on this page came off a stopwatch, a database or somebody’s published price list. These are judgments, and they are here so you can disagree with a specific one rather than with the total.
Pages opened in a sitting: 6 pages
Today, review, and a few looks at the dictionary or a grammar page on the way past.
New spoken clips a learner fetches in a month: 60 clips
A phone keeps 400, so only new words cost anything. This is roughly the new cards a month at the default pace, plus their sentences.
Characters in a spoken phrase: 30 characters
A word is about eight and a recorded sentence about forty. Speech is billed per character, so this is what decides that line.
Questions a learner asks Anu in a month: 4 questions
The per-person cap is ten a day, so this is far under it. Most people never open her.
Pieces of writing a learner has looked at in a month: 8 notes
Cheaper per call than a question and asked more often, because the writing exercise offers one every time.
Emails a learner is sent in a month: 3 emails
A mailed sign-in link lasts a session, so this is a couple of sign-ins and the occasional reminder.
Processor time behind one request: 40 milliseconds
A page is mostly waiting on the database, which is not charged. This is the part that is, and it is the softest number here.
What one page reads out of the database: 25 kilobytes
Eight or so queries over a deck and a review log, none of which return much.
Learners on the app at the same moment, at the busiest: 3 per cent of the month's learners
A class arrives together, so this is higher than it looks. It decides the database instance and nothing else.
Times the shared JavaScript is re-fetched by a device in a month: 4 times
It is cached until a deploy changes its name, so this is really how often the app ships.
Taken on 2 September 2026, against Postgres 16 on one machine and a production build served locally. Each row says what to run to get the same number, because a figure nobody can reproduce is a claim rather than a measurement.
| What | How much |
|---|---|
| The dictionary, in Postgresnpm run db:seed, then pg_total_relation_size over Lexeme and Form | 20 MB for 6,110 entries and 39,421 forms, indexes included |
| Postgres itself, before a single rowpg_database_size on the empty schema, subtracted from the seeded one | about 8 MB |
| One review80,000 rows written by scripts/load-fixture.ts, divided into the table size | 300 bytes, with the four indexes that make it readable |
| One cardthe same fixture, 2,000 cards | 352 bytes, indexes included |
| A year of one learner, at fifteen reviews a day five days a weekthe two rows above, times the default daily goal in lib/settings/store.ts | 3,900 reviews and a starter deck of about 400 cards, so 1.3 MB |
| One spoken phrase, as storedone request to TartuNLP for a three-word sentence, passed through prepareClip in lib/audio/wav.ts, read back off the WAV header | 51 KB for 1.15 seconds, which is 43 KB a second |
| What that speech actually isthe fmt chunk of the same file, before and after | 16-bit PCM, 22,050 Hz, one channel, no compression; the service sends 32-bit float with half a second of silence each end, 199 KB for the same sentence |
| A page, as HTML over the wirecurl --compressed against the built app, seven routes | 14 KB for the dictionary, 88 KB for the whole course page, 21 KB in the middle |
| The JavaScript every page sharesthe First Load JS line of next build | 102 KB, fetched once per build and then cached |
| Requests behind one page viewChrome DevTools request counts over seven routes, twice each | about 35, of which 11 to 15 reach the server once the browser cache is warm |
| What a phone keeps, so it stops askingLIMITS in public/sw.js | 400 spoken clips, 220 build files and 60 pages |
| Loading the whole dictionary into an empty deploymenttime npx tsx prisma/seed.ts | 3.4 seconds |
Two of those are worth stopping on. A review row is 300 bytes, so a learner costs about 1.3 MB a year and the whole review log of a thousand people for a year fits in less space than a phone photograph album. And a spoken clip is uncompressed audio, 43 KB for every second of it once trimmed and stored as 16-bit, which still makes speech the largest thing this app moves by a wide margin. Turning the audio off in the panel above is the single biggest saving available, and it is also the feature hardest to argue for losing.
Read on 2 September 2026. These are the numbers most likely to be out of date by the time you read this, which is why they carry a date rather than being folded into the total.
Ekilex, Wiktionary and TartuNLP are not on that list, because they do not charge and this page does not pretend otherwise. They are credited above instead, with what each one gives and the license it comes under. Where buying the same thing is possible the panel says what that would come to, so the size of the gift is visible, and that figure is in no total here.
Somebody’s time, which is the largest real cost of this project by a long way and is not a hosting bill. The panel above prices machines. It does not price writing the course, checking 5,363 English glosses against their sources, or reading the queue of corrections learners send in.
Answering people. A dead end in this app offers to send a report, and somebody has to work through them for that to mean anything.
A bad month. The projection is a steady month. It does not model the week something is on the radio, and a plan’s included allowance is exactly where a spike is felt first.
Four things, in the order they would matter.
The daily cap on the tutor could go up. Every model call in the app is booked against a shared budget of $20 a day, which cannot be turned off and is what stops the one line that could run away. Raising it is a knob with a stop on it rather than an open check, and at ten thousand learners it is already the thing holding that line down.
A school could keep its history. Everything on the progress screens is worked out from the review log on each request rather than stored, so the log is never thrown away and the database only grows. That is the right design and it is what makes the instance ladder the steepest line on this page.
The corrections could be worked. The dictionary is built from Ekilex and Wiktionary rather than typed, which keeps invented Estonian out of it and does not make every entry right. Learners already report the wrong ones.
Something could go back to the institutions this is built on. Ekilex, Wiktionary and TartuNLP ask for nothing and there is no suggestion they should start. But this app would not exist without any of the three, and at a size worth funding the decent thing is to support the work rather than only to use it: a contribution, a corrected entry sent back, or paying for the compute somebody else is currently absorbing.
There is no advertising, no analytics script and no third-party tracker on any page of this app, which the privacy page states and the code keeps true: an analytics package was mounted here once, on every visitor of the hosted build, while that same notice said there was none. It was removed rather than the notice being edited.
Nothing about a learner is sold, shared or used to train anything. Whether a teacher can see a pupil is answered narrowly and separately, and the answer is effort rather than contents. Every one of those promises costs money to keep rather than saving it, which is most of why this page exists.