Osy# · Why a language
Why a language?
An application has facts that must stay true across all of it. Each of them spans more than one part of the program, so none of them belongs to any one part.
- A person sees only what they may see.
- A payment is made once.
- A rename keeps the data.
- What the application did can be explained.
Who may see a record is a fact about the rule and about every read that could reach the record. A payment made once is a fact about the call, the crash that might interrupt it, and the restart. A rename that keeps its data is a fact about the declaration and about the rows. An explanation is a fact about a decision and the rule that produced it.
Osy# is a language so that one compiler sees all of those parts as one program, and facts like these are its job rather than a promise.
01
A fact declared once can be held. A fact spread across several places can only be kept in agreement.
The rule about who may see a record is written once, on the record's entity. The compiler puts that rule inside every query and every write over the entity, wherever in the program it comes from. No read has to repeat it, and no read can leave it out.
A rename that keeps its data has the same shape: the compiler has the declaration before and after, and knows the rows, so the change is checked against both and refused until a migration says what it means.
The other two are not declarations that live in one place; they are how the program executes. A payment made once is a property of a call: you write the ordinary call, the compiler finds that it leaves the platform, and the runtime records it as it completes, so a restart resumes after it. An explanation is derived from the declarations together with the record of what ran.
What the four share is not one place but one model. Because the rule, the call, the declaration and the record are parts of the same program, the compiler and the runtime can derive the relationships between them and enforce them, instead of people keeping them in agreement.
One model, so the relationships between its parts are derived and enforced, not kept in agreement by hand.
02
One program is what lets the compiler know enough.
When the data, its rules, the functions, the screens and the processes are one program, the relationships between them are visible to the compiler. It can check them before the program runs, enforce them while it runs, and explain them afterwards.
Before it runs. A page open to everyone that reads an entity granting anonymous visitors nothing is legal on both sides and wrong as a whole. The compiler sees the page, its query and the entity's rule at once, and warns, naming both sides and the fix. A verb in a query that cannot become a database statement is refused rather than run quietly over every row.
While it runs. The access rule is inside every statement. A live read stays current as the data it read changes. A process parks in a state until someone who may act does, for hours or days, and it outlives the deploy that started it. A call that leaves the platform is a durable step, found by the compiler: its result is recorded as it returns, and a restart reuses the record instead of making the call again.
Afterwards. Who may read and write what is answered from the declarations, in plain words. What actually ran is answered step by step. A rule that can deny is proven by running the application as the people it governs.
Checked before, enforced during, explained after: all three because the compiler sees the whole program.
03
A guarantee can only be as broad as the model that enforces it.
Whatever enforces a property can hold it only over the parts it can see.
The guarantees above are not features a program calls; they are what its declarations mean. A rule on an entity means the rule is inside every statement over it. A live read means a value that stays true. A state in a workflow means a run that waits there and survives. Because they are meanings, they hold everywhere the language is used, with no convention to remember and no call site to forget.
A fact that spans a read, a write, a page and a process needs an enforcer that sees all four. Osy# gives its compiler and runtime an application model that covers the data, its rules, the functions, the screens, the processes and the tests, and that is what lets these properties be semantics of the program rather than conventions its code follows. That is why they belong in the language.
The guarantees are semantics, so they hold wherever the language is written.
04
More of your code is written by something that cannot ask a colleague.
The cost of a new language was never its syntax. It was everything that accumulated around one: the conventions, the patterns, the libraries, and the people who knew them. The next reader learns a language from its reference and asks its compiler, and needs neither a colleague nor a tradition.
That reader is served by a program in which more is explicit. It can ask what the application is, who may read and write what, whether a change is valid, and what actually ran, and get answers derived from the program rather than inferred from it. Osy# is shaped like C#, so what is familiar stays familiar, and what is new is what the compiler now holds.
The more code is written by something that cannot ask, the more of the application has to be explicit.
05
What a language asks of you.
It is a language, so there is one to learn. Most of it is C#, and the parts that are not are the parts that hold the facts above.
The compiler decides where each part of the program executes. It warns when declarations that are each legal combine into something that is probably not what you meant, such as a public page that reads an entity granting anonymous visitors no rows. It refuses what it cannot make true: a query whose verb has no database form, a deploy that would drop a column holding data, an in-place deploy that would move a run parked mid-body, a migration that does not say what happens to every parked state. Accepting those decisions is the trade. It is a beta, so things will move between versions, and a version that moves does not break one you already shipped.
Everything you build is yours. The source is yours, the applications we publish are yours to fork under the MIT licence, and the same compile runs wherever Postgres is. How an application is hosted and operated is osyrin.com's question, not this site's.
Proof
We run on it.
The platform's own control plane, the application that manages organisations, zones, placements and releases, is written in Osy# and compiled by the same compiler.
252 entities · 3,529 functions · 196 components · 38 workflows · 1,896 tests · 153,458 lines of Osy#, counted by the compiler when this page was built.