SPy and Mojo: first impressions vs. deeper reality

.

About these notes

This post was generated by a LLM (generative AI) from an exploratory conversation. I guided the discussion, challenged the AI’s conclusions, and verified the technical content.

These notes summarise a conversation comparing SPy and Mojo — two projects that share a surface motivation but diverge deeply in goals, philosophy, and design. The discussion starts from the “obvious” comparison that most readers would make, then systematically corrects and deepens it.

The Surface Similarity: Why People Compare Them at All

At first glance, SPy and Mojo look like they are solving the same problem. Both use Python-like syntax. Both aim for C-like performance. Both use MLIR somewhere in their compiler stack. Both target GPU as a backend (Mojo now, SPy eventually via numbacc). Both are led by people with deep compiler expertise — Antonio Cuni (PyPy, HPy) for SPy, Chris Lattner (LLVM, Swift, MLIR) for Mojo.

A reader skimming tech news would probably conclude: “two competing approaches to the same problem — fast Python.” This is understandable, and it is not entirely wrong. But it misses almost everything that matters.

The naive comparison

Taking this surface view at face value, here is how the two projects look:

SPy

Mojo

Goal

Research: correct semantics for compilation

Product: fast Python for AI/ML

Python compatibility

Deliberately breaks it

Aims to be a strict superset

Compiler IR

C (via cwrite), MLIR only in numbacc

MLIR + LLVM throughout

GPU support

Future, via numbacc/MLIR

Production-ready (NVIDIA, AMD)

Open source

Fully open (MIT)

Stdlib open, compiler closed

Team size

~1–5 people

Large engineering team at Modular

Maturity

Pre-alpha

Approaching 1.0

WASM target

First-class

Not a stated goal

This table is not wrong. But it frames the comparison badly, and several of the entries deserve to be challenged.


Correcting the Picture

SPy is not pure research

The most important correction to the naive view is about SPy’s purpose. Antonio Cuni works full-time on SPy, funded by Anaconda. The goals listed in the Zen of SPy are concrete engineering goals:

  1. Easy to use and implement. The language is easy to understand. Moreover, it must be possible to implement SPy without huge engineering teams.

This is not the language of academic research — it is the language of deliberate, practical engineering with real constraints. Anaconda is not funding SPy purely for intellectual interest. The practical vision is a language that can be used alongside Python in the scientific and data ecosystem — the same ecosystem Anaconda serves.

Two independent languages, two different relationships with Python

This is the subtlest point in the comparison, and the one most easily flattened by a quick reading.

Both SPy and Mojo are genuinely independent languages — neither is Python, and both can produce standalone binaries that carry no Python dependency at runtime. The SPy AWS Lambda demo is an instructive example: a SPy function compiled to a self-contained native binary and deployed as an AWS Lambda custom runtime, with no CPython interpreter involved whatsoever. The cold start time of such a binary is dramatically better than a Python Lambda — no interpreter to initialise, no packages to import, just a small native executable. This is a deployment mode that has nothing to do with Python at all.

Mojo is equally capable of standing alone. It can produce fully native binaries, and its systems-programming features (ownership, struct , manual memory management) are designed precisely for code that never touches a Python runtime.

So the distinction is not “companion vs. independent.” Both languages sit on a spectrum, and both occupy multiple points on it simultaneously. The real difference is in where the centre of gravity lies — what the language is primarily optimised for, and what relationship with Python feels most natural to its users.

SPy’s centre of gravity is close to Python. Cuni states it clearly:

SPy still aims to have a very tight integration with the existing Python ecosystem. It is possible to import Python libraries from SPy, and SPy modules from Python.

The .spy file extension is a deliberate signal. The design goals — easy to learn for Python users, bidirectional import, tight ecosystem integration — all point toward SPy being most at home as a sibling language. Think of it as what Cython or RPython aspired to be: a way for Python library authors to write high-performance code that their Python users can consume naturally, without learning a new paradigm. The standalone binary mode is a genuine and useful capability, but it is not the primary story.

Mojo’s centre of gravity is further from Python. It introduces ownership, borrow checking, struct vs class , fn vs def , and other concepts from Rust and C++ that are foreign to Python developers. Its aspiration to become a Python superset is real, but its design is shaped more by the needs of systems and GPU programming than by the needs of Python library authors. Mojo can call Python packages and produce Python extensions, but the learning investment required pushes it toward being used as a primary language rather than as a complement.

This is not a value judgement — it is a difference in orientation that leads to different strengths and different natural audiences.

Mojo’s “superset” claim deserves scepticism

Cuni addresses this directly, though without naming Mojo:

The myth of 100% compatibility — the vast majority of “compilers for Python” which exist or existed in the past are not 100% compatible. They don’t support the full language even when they claim so. SPy prefers to be more explicit and honest about it.

Full Python compatibility in a compiled language would require supporting __class__ reassignment, metaclass magic, dynamic module mutation at runtime, the full CPython C API, and dozens of other features that are essentially incompatible with ahead-of-time compilation. The practical subset of Python that Mojo will realistically support is likely to be similar in scope to what SPy targets — SPy is simply honest about this from the start.

This is not a criticism of Mojo as such. It is a criticism of the framing. In practice, neither language needs to be a true superset to be extremely useful.

SPy will feel closer to Python for most Python users

Mojo introduces struct , fn , var , let , ownership semantics, and borrow checking — concepts borrowed from Rust and C++ that most Python developers have never encountered. The learning curve is steep even when the syntax looks familiar.

SPy’s ambition is different:

I expect that for a large fraction of Python users, it will not matter [that SPy is not Python]. There are many users who mainly consume complex libraries written by others and write “straightforward” Python code: for them, writing SPy should be as easy as writing Python.

The features that SPy removes are the obscure corners of Python — the dynamic dispatch machinery that most Python users never consciously rely on. The features it adds (static typing, zero-cost abstractions, rich metaprogramming) are things that good Python programmers already reach for via type hints, dataclasses, and decorators. For this audience, SPy should feel like a natural step, not a new language.

Simplicity as a design constraint

Mojo is backed by a large engineering team at Modular. The Modular platform has hundreds of thousands of lines of open-source code and thousands of contributors. This is a well-resourced product effort.

SPy’s first design goal is explicitly the opposite:

It must be possible to implement SPy without huge engineering teams.

This constraint shapes the entire language. Features that would require enormous compiler infrastructure are excluded or deferred. This is not a weakness — it is a deliberate bet that a simpler, more auditable language with a smaller implementation is more sustainable and more trustworthy for library authors who need to understand what is happening under the hood.

SPy as a better RPython

This angle is almost entirely absent from the naive comparison, yet it may be one of SPy’s most interesting long-term possibilities.

RPython is the restricted Python-like language in which PyPy itself is written. It is a statically compilable subset of Python used to implement high-performance interpreters and runtimes. Antonio Cuni is a PyPy core developer — he knows RPython’s strengths and limitations intimately.

SPy can be seen as the next iteration of that idea: a clean, statically compilable Python variant (not just a subset — it adds new features that RPython lacks) that could be used to implement interpreters, language runtimes, and other systems-level tools. Mojo has zero interest in this space. If SPy matures in this direction, it would fill a gap that nothing else currently fills well.


Are SPy and Mojo Competitors?

Not really — at least not in the way the word “competitor” normally implies.

They target overlapping but distinct audiences and use cases:

  • Mojo targets AI/ML engineers who need to write custom GPU kernels and high-performance numerical code, and who want to do it in something that feels like Python. It is a product, commercially backed, with GPU as a first-class concern.

  • SPy+Python targets Python library and package authors who need performant extension code that integrates naturally with the Python ecosystem, without requiring their users to learn a new language. WASM as a first-class target gives it a portability story Mojo does not have.

The overlap — Python package authors who need high-performance kernels — is real, but both languages could coexist in that space, serving different preferences and constraints. “Alternatives” or “different bets on the same problem space” is a more accurate framing than “competitors.”

The more interesting question, which will only become practical when Mojo’s compiler is fully open-source and SPy is substantially more mature, is: how will the Python community — and in particular the maintainers of major packages — actually adopt these tools? Will they gravitate toward SPy’s simplicity and Python-native integration, or toward Mojo’s GPU maturity and commercial backing? That question has no answer yet.


A Revised Comparison

With all of the above in mind, the table looks rather different:

SPy

Mojo

Standalone binary?

Yes (e.g. AWS Lambda demo)

Yes

Python integration

Bidirectional; tight by design

Possible but secondary

Centre of gravity

Close to Python (sibling language)

Further from Python (systems language)

Primary audience

Python library/package authors; systems builders

AI/ML engineers; GPU kernel authors

Honesty about compatibility

Explicit and upfront

Aspirational (“superset”)

Feels like Python?

Yes, for most users

Steeper curve (ownership, structs, fn/def)

Design constraint

Implementable by a small team

Large team, large codebase

WASM

First-class target

Not a stated goal

GPU

Future (via numbacc/MLIR)

Production-ready (NVIDIA, AMD)

RPython successor potential

Yes

No

Open source

Fully open (MIT)

Stdlib open; compiler by ~2026

Maturity

Pre-alpha

Approaching 1.0


Conclusion

The naive comparison of SPy and Mojo as two competing approaches to “fast Python” is a reasonable first impression but it flattens what are actually quite different projects with different philosophies, different audiences, and different long-term bets.

SPy’s honesty — about what it is, what it is not, and what it will cost to build — is one of its most distinctive qualities. So is its vision of tight, reliable Python integration rather than an aspirational superset claim. These are not consolation prizes for being smaller; they are coherent design choices that give SPy a distinct and plausible path forward.

Whether SPy can reach sufficient maturity and sustainability to realise that path is the open question. The ideas are sound. The funding is real. The community is small but the expertise is deep. The next few years will tell.

References