Mahdi
All posts
vlanguage-designmaturity

How mature is V, in numbers rather than adjectives

What the repository, the release cadence and the standard library actually say about V's state in 2026, and the one thing that decides whether a project can depend on it.

"Mature" gets used for two different things: is the project healthy, and can I depend on it. V is in an unusual position where those two answers diverge, so it is worth separating them.The project is healthyStraight from the GitHub API:Stars37,936Forks2,292Watchers458Open issues88LicenceMITCreated2019-02-08Last push2026-09-30ArchivednoThat is a project with seven years of continuous work, three to four thousand issues handled, and about three contributors a day pushing to master. It is not abandoned, and it is not a hobby project with a weekend following.The releases are frequent and the binaries exist
0.5.2      2026-07-12
0.5.1      2026-03-09
weekly.2026.08   2026-02-17
weekly.2026.07   2026-02-09
weekly.2026.06   2026-02-03
0.5        2025-12-31
Roughly a release every three to four months, with weekly builds in between. 0.5.2 ships five platform archives — linux, linux_arm64, macos_arm64, macos_x86_64, windows — so cross-compilation is a supported path rather than something you assemble yourself.Note what the version numbers mean, though. This is a language at 0.5 after seven years. Go was at 1.0 in August 2012, three and a half years in. V has had a stable-looking release cadence and a pre-1.0 number for its whole life, and the last commit I pulled was v3: fix the compiler bugs that stopped the Vinix kernel from compiling — the compiler itself is still being fixed hard enough that a kernel will not build without the fixes.Master is not a releaseThis matters more than any of the numbers above.The commit you get from git clone is not what a release gives you. I hit this installing V: the checkout was on master, v.exe had been rebuilt from a newer commit than the vlib beside it, and every standard-library import failed with
builder error: cannot import module ""time"" (not found)
with vlib/time/chrono.v sitting right there containing module time. Setting VROOT did nothing. Going the other way — an older binary against a newer vlib — produced unknown type 'u128' from inside vlib/builtin/int.v.The compiler and the standard library are versioned together in a release zip and versioned independently in a checkout, and nothing checks that they agree. A clone-and-build V is not a supported configuration; the release is. That is a larger gap than "the language moves fast" — it means the default thing a new user does produces a broken install with error messages that blame the standard library.The standard library is the weak partstrings has five public functions:
random
find_between_pair_u8
find_between_pair_rune
find_between_pair_string
split_capital
There is no strings.split, no strings.to_lower, no strings.trim. In Go that module is the one you reach for constantly. In V, string handling is methods on the type:
parts := "a,b,c".split(",")
println(parts.join(","))
println("mahdi".to_upper())
println("a-b-c".replace("-", "/"))
println("  x  ".trim_space())
That is a defensible design and I do not mind it — arguably split belongs to a string more than to a namespace. But it means porting Go code fails at every string call, and it means the standard library you would reach for first is thinnest exactly where Go is strongest.I could not find strings.replace_all, strings.count, strings.index_any, or anything resembling strings.NewReplacer. For a language whose pitch is that it is batteries-included, strings is where I would spend the next round of work.The thing that would decide this for a projectThe formatter is not idempotent. This is the finding I would weight heaviest, because it is not about performance or adoption:
v fmt -verify fmt.v
fmt.v is not vfmt'ed
> Encountered a total of: 1 formatting errors.
That file had just been through v fmt -w. Formatting twice produces a different result from formatting once, so you cannot use v fmt -verify as a CI gate the way gofmt -l works. The workaround is to run v fmt -w and fail if git reports a change, which is a different and worse thing: it fails on the first commit rather than on the offending file, and it cannot be run on files it has not been allowed to rewrite.A formatter that does not converge is a bug that will hit every team. It is one of the cheapest fixes in a language and it blocks adoption more than a missing library does.Where it landsThe project is not the risk. Seven years of work, a maintainer who ships weekly, 38,000 stars, 88 open issues — that is a healthy project with a lot of people using it, and none of that is in doubt.The risk is that the compiler and the standard library move together at a pace where nothing guarantees they agree, and where the one thing a team depends on daily — a formatter that converges — is not yet solid. strings being thin is an inconvenience; a non-idempotent v fmt is what makes a shared repository harder than it should be.I would use V for a single-file CLI or a scratch tool today, with no hesitation. I would not start a shared service on it, and the reason is the formatter rather than anything about the language design — which is otherwise better than Go's in the mutability default and better than most languages at compile speed.

Related