To share these ideas with the broadest possible audience, this manifesto has been translated from its original version with the assistance of AI tools. As English is not my native language, I ask for your understanding of any awkward phrasing or nuances that may have been lost in translation. The substance of this work—the philosophy, the architecture, and the vision for CScaf—is, however, entirely my own.
This manifesto deconstructs a silent crisis in modern software development: our programming languages are fundamentally built on an obsolete ‘One Computer’ model, forcing us into the immense complexity of the Cloud Native ecosystem. Microservices, containers, and endless YAML are not a solution, but a massive, costly life-support system for tools that are no longer fit for our distributed reality. This fragmentation has exploded cognitive overhead, rendered our IDEs powerless, and created a false dichotomy between productivity and performance.
This work proposes a new paradigm to solve this crisis at its root: Structural-Oriented Programming (SOP), a superset of OOP realized in a new language called CScaf. The core idea is to elevate architectural concerns—services, deployment models, and communication contracts—into first-class, compiler-enforced citizens of the language itself.
In this new model, a single, unified codebase can evolve from a high-performance monolith into a distributed network of microservices by changing a single line of configuration, not through a multi-year rewrite. The compiler, not human convention, guarantees the safety of network communication and enables fearless, system-wide refactoring. This manifesto lays out the philosophy, architecture, and core mechanisms of CScaf, offering a vision for a future where we manage the essential complexity of our business logic, not the incidental complexity of our tools.
To understand the complexity of modern software architecture, we must return and examine the foundational, almost invisible assumption that has shaped every mainstream programming language we use today. From Fortran and C, to Java and C#, all were born from a single mental model: a program is written to be executed on a single computer, within a single memory address space.
The history of abstraction in computer science is a series of efforts to hide the complexity of the underlying hardware. Assembly abstracted away machine code. Procedural languages like C abstracted away the register architecture and jump instructions. Object-Oriented Programming (OOP) abstracted away the organization of data and behavior. But all these layers of abstraction operate within the same primal “sandbox”: a single process, running on a single kernel. The entire memory safety model of Java and C#, the thread management mechanisms, and the type system are all optimized for the internal world of a single process. They were not designed with an awareness of a world existing beyond that boundary.
However, the reality of large-scale applications in the Internet era has completely shattered this assumption. No significant application today runs on just a single computer. They are distributed systems, comprising hundreds, even millions of processes, spanning multiple data centers.
The conflict between a programming model designed for “one machine” and a deployment reality that demands “many machines” is the origin of nearly all the complexity we face. The entire Cloud Native ecosystem—microservices, containers, Kubernetes, service mesh—is not a natural evolution of programming. They are an extremely complex life support system, invented to compensate for the primal deficiency of our programming languages themselves. We are using a massive layer of infrastructure to “patch up” and “deceive” programs written for one computer into believing they can operate in a distributed world.
The collapse of the “One Computer” model created a vacuum. A new architectural pattern was needed to cope with the demands of the internet era, and the industry responded with microservices. The promise was seductive: small, independent services, developed and deployed autonomously, allowing for greater scalability and team velocity.
But this was an illusion of progress. We did not solve the fundamental problem of complexity; we merely shifted its location. We took the complexity that was once managed inside a single, monolithic codebase and externalized it into the lawless, compiler-unaware void between services. This is the space where contracts are fragile, where observability is a Herculean effort, and where a single change can have an unknowable “blast radius.”
To manage this new, externalized complexity, the entire Cloud Native ecosystem was born. It is, as stated before, a massive life support system. Kubernetes, service meshes, API gateways, and endless YAML files are not a natural evolution of programming. They are a complex superstructure of tooling built to compensate for a single, profound failure: our programming languages have no native concept of a distributed system.
This tooling-based approach comes at a staggering cost:
The IDE Becomes Dumb: Our most powerful development tools are rendered impotent. “Go to Definition” stops at the edge of a process, hitting a dead-end at an opaque network call. Static analysis, which provides a safety net within a service, is blind to the system as a whole. Refactoring a core data model across services becomes a task of archaeology and fear, not a safe, automated operation.
The Cognitive Burden Explodes: Developers are no longer just developers. They must become DevOps experts, fluent in the intricate configuration of schedulers, proxies, and network policies. The business logic is now buried under layers of infrastructural boilerplate. We are managing infrastructure, not building systems.
The Contract is a Lie: The “contract” between services—whether an OpenAPI spec or a .proto file—is a human convention, not a machine-enforced guarantee. It exists outside the type system and is constantly at risk of becoming outdated. This reliance on human convention over machine-enforced truth is a compromise we should never have been forced to make. If this model of trust truly worked, why do even the most disciplined engineering organizations, like Google and Facebook, still suffer global outages caused by a single module being deployed days, or even hours, before its dependencies are updated? This is a classic dependency mismatch—a class of error that should be impossible, a trivial catch for any compiler aware of the entire system. Instead, we have traded the compiler’s rigorous, instantaneous validation for brittle, runtime-only checks, effectively turning billions of users into a distributed, live-action compiler, tasked with discovering our logical syntax errors at the cost of global service availability.
This is not an indictment of the brilliant engineering behind these tools. The Cloud Native ecosystem is a marvel of human ingenuity. It is, however, an indictment of the paradigm that made it necessary. We are behaving like developers who use an Object-Oriented language but still think procedurally, writing only static methods inside classes. We have the new container, but we are still clinging to the old way of thinking. Similarly, we are forcing single-process languages into a distributed reality, and this entire ecosystem is the complex, expensive translation layer we’ve been forced to invent.
This approach is not just complex. It is a sign that our foundational tools are failing us. If they were truly sufficient, we must ask ourselves some hard questions:
Why did Facebook spend billions of dollars creating Hack and the HHVM, a monumental effort to re-engineer PHP simply to make it perform at the scale their business demanded?
Why do companies like Grab, Netflix, and Twitter invest fortunes not just in business logic, but in building vast, bespoke tooling ecosystems just to manage the growth and interaction of their services?
Why has DevOps, a field intended to streamline development, become a major cost center, with countless engineering hours dedicated to deployment and configuration management?
Let us be clear: the engineering behind the Cloud Native ecosystem is a monumental achievement. It is a testament to human ingenuity in the face of immense complexity. But it is an achievement born of necessity, not of design. It represents a paradigm mismatch of epic proportions. We are attempting to build distributed systems while still thinking in the language of a single process, and the entire tooling ecosystem is the complex translation layer we’ve invented to bridge that gap. It is the modern equivalent of using a powerful Object-Oriented language but thinking in a purely procedural way, resulting in a codebase of nothing but static methods. The tools work, but they betray a fundamental flaw in the approach. If our current languages and their single-process model were truly sufficient, why would this be necessary? Why did Facebook have to invest billions creating Hack and the HHVM to escape the limitations of PHP? Why must companies like Grab, Twitter, and Netflix build and maintain massive, bespoke tooling ecosystems just to manage their growth? Why has the cost of DevOps exploded, with countless engineering hours spent on YAML configuration and deployment orchestration instead of business logic? The existence of Google’s Piper monorepo is perhaps the most telling evidence. It is a profound statement that a unified, single source of truth is essential for managing complexity at scale. Yet, our languages cannot natively support this reality, forcing the creation of yet another layer of incredibly complex tooling. Now, imagine an alternative. Imagine if Google’s entire repository was a single, monolingual project. An IDE that understands the whole system, where “Go to Definition” on a search query could instantaneously trace the call from a web frontend, through the indexing service, to the ranking algorithms, even if they are destined to run on millions of machines across different continents. Imagine refactoring a core model and having the compiler, not human toil, guarantee its safety across the entire system. All the boilerplate for service communication vanishes. Deployment becomes as simple as installing a single entry point on the target machines. How many teams and how many months would it take today to map the precise function call chain of a single Google search click? The answer is a matter of speculation, but it would be a monumental effort. With a language that integrated this understanding from first principles, it would take a single press of F12. All of this, with the same, if not better, performance than the current model. How amazing would that be?
The architectural fragmentation we described, which necessitates the massive tooling workaround of the Cloud Native ecosystem, is not born from a single flaw. It is fueled and justified by another historical divide, a trade-off we have accepted as an inevitability: the choice between Productivity and Safety versus Performance and Control.
The history of programming languages has diverged down two distinct paths:
The Path of Managed Languages: Originating with Lisp and Smalltalk, and successfully commercialized by Java and C#, this path prioritizes developer safety and productivity. By introducing an intermediate runtime (JVM, CLR) with a Garbage Collector (GC), they eliminated a whole class of dangerous memory management errors and allowed teams to build complex applications quickly. However, the price to pay was the loss of low-level control. Programmers are separated from memory and hardware by a layer of abstraction, creating a performance “ceiling” and unpredictable latency, which is unacceptable for applications requiring ultra-low latency.
The Path of Systems Languages: Inheriting the legacy of C, this path, modernized by C++ and more recently Rust, prioritizes performance and absolute control. These languages provide direct memory access, allowing for optimization down to the individual instruction cycle. This makes them the mandatory choice for high-performance computing (HPC), embedded systems, and core operating system components. The cost is a harsh programming experience, a steep learning curve, and the constant burden of manual memory management weighing on the developer.
This dichotomy is not merely an academic issue. It has direct and costly architectural consequences that feed directly into the microservice crisis. It forces organizations to build polyglot systems, a split that the microservice architecture then institutionalizes. Business logic, where development speed is key, is written as a suite of services in C#. The core algorithmic or data-processing services, where performance is paramount, must be written as a separate suite of services in C++. We are forced to break our system apart not just by logical domain, but by the very limitations of our languages.
We are stuck. We are stuck with languages designed for a single computer in a world of many computers. We are stuck with a tooling ecosystem that patches over this flaw at a massive cost. And we are stuck with a false choice between building productively and building performantly, which justifies breaking our applications apart even further.
These problems converge to create an unavoidable outcome: a brutally fragmented codebase, often scattered across different languages and deployment pipelines. This fragmentation is not an enlightened architectural decision; it is a symptom of the deep limitations within the very tools we use.
But why must we accept what is merely “good enough” when we can have something better? Was Assembly not created to replace raw binary for this very reason? Did C not supplant Assembly for the same? We have engineered an entire ecosystem of tooling for microservices precisely to stop relying on fragile, human-to-human trust, yet we stop short of creating something that solves the problem at its root. Why, in this century, do we not demand a similar leap forward for the problems of our own making?
To build the systems of the future, we do not need a better framework or a smarter DevOps tool. We need a new kind of tool—a language built on a fundamentally different set of assumptions.
The history of computer science is, in essence, the history of abstraction. Every leap in productivity and capability has come from inventing a new layer of abstraction, allowing us to manage a greater scale of complexity. We evolved from abstracting machine instructions (Assembly), to control flow (Procedural Languages), and then to code organization (Object-Oriented Programming - OOP).
Each of these evolutionary steps did not completely replace the last; it built a new layer upon it. OOP, for all its revolutionary power, still operates within the sequential execution model of procedural languages. Today, we stand before a new wall of complexity. The source of this complexity no longer lies inside a single class or module. It lies in the structure, interaction, and deployment environment of the large-scale components within a system. OOP lacks the vocabulary and the fundamental concepts to describe and manage this type of complexity.
This is where the next evolution is needed: Structural-Oriented Programming (SOP).
SOP is not a replacement for OOP. It is a superset, a new layer of abstraction built on top of OOP. If OOP is about the micro-architecture of objects, then SOP is about the macro-architecture of the entire system. The core philosophy of SOP is to elevate architectural concepts—the very things currently managed by YAML files, DevOps tools, and unwritten conventions—to become first-class citizens of the programming language itself. CScaf is the first effort to realize this philosophy.
This approach is built on a foundational promise, a guiding principle for this new era of development:
“Code once, grow forever.”
This doesn’t mean code is written once and forgotten. Instead, it speaks to a new reality. “Code once” refers to the ability to build an entire system, from a simple MVP to a global-scale platform, within a single, coherent codebase. “Grow forever” is the promise that this codebase’s architecture can evolve and adapt to any scale requirement without the need for costly “rip and replace” rewrites. It promises sustainable growth, where complexity is managed by the language, not by human brute force.
Space is the central concept of CScaf. A Space is a complete logical service, an architectural unit that can be deployed and executed independently.
The origin of Space is not the need for sandboxing, but rather the acknowledgment of a fundamental truth of modern systems: a logical component does not necessarily exist in the same physical space as other components. In a large-scale application, your BillingService might be running on a server cluster in Virginia, while the UserService runs in Frankfurt.
Current languages have no native concept to describe this reality. CScaf makes this reality a first-class citizen. When you define a Space, you are telling the compiler: “This component is, conceptually, an independent entity. Treat it as if it could be anywhere in the world.”
The isolation of a Space is not an artificial “fence” erected for security. That isolation is the natural consequence of the fact that it can be deployed to a different physical location. You cannot directly access the memory of a server on the other side of the globe, and therefore, the language does not allow you to do so either.
But this concept of isolation extends beyond mere physical location. It also defines the very rules of execution within that boundary. A Space is the container where you make the critical choice: does this module require the safety and productivity of a Garbage Collector (GC), or does it need to be pushed to the absolute limits of performance without one?
This creates a powerful evolutionary path. A team could initially build a service within a Space that uses a GC for rapid development and maintenance. Later, if that specific service becomes a performance bottleneck, they can rewrite its internal logic to operate without a GC, all within the same architectural boundary.
Contrast this with the current approach: creating an entirely new microservice in a different language. While both scenarios require rewriting the core logic, the CScaf approach is fundamentally superior. The communication contracts, the deployment story, and the guarantee that this rewritten module still functions correctly within the big picture are all managed by the language itself. Any integration errors are caught by the compiler, long before a single user is affected.
Mode is the property of a Space that formalizes the very trade-off we just discussed. It is the primitive that allows the programmer to finally break the “Productivity vs. Performance” dichotomy at a granular level. It explicitly defines the physical laws that govern its Space’s universe.
Why is this explicit declaration necessary? Because a modern application is not homogenous; it is a composite of components with vastly different requirements. The payment processing logic demands the absolute memory safety of a Managed environment with a GC. The core recommendation algorithm, however, requires the raw, unabstracted performance of an Unmanaged environment without a GC.
Current languages force you to cleave these components into separate codebases, often in different languages, institutionalizing the polyglot fragmentation we’ve criticized. Mode allows you to declare that critical trade-off on a per-Space basis, all while keeping the components harmoniously within a single, unified codebase.
While initially, this might manifest as a binary choice—Managed or Unmanaged—the term Mode is chosen to represent a future spectrum of possibilities. One can imagine future modes optimized for specific hardware like GPUs, or modes with different memory allocation strategies. It is not just a simple switch on a complex circuit board; it is the dial that tunes the fundamental physics for each isolated component of the system.
Finally, Runtime is the primitive that allows a developer to shatter the agonizing, and often permanent, trade-off between a Monolith vs. Microservices architecture.
Why is this necessary? Because in software development today, this architectural decision is typically made once, at the beginning of a project, and reversing it is a monumental undertaking. Teams are forced to choose: build a monolith for initial simplicity and high performance, at the risk of it becoming an unmaintainable beast? Or start with microservices, paying a massive upfront complexity tax in tooling and infrastructure for the promise of future scalability?
The Runtime property of a Space makes this a fluid, reversible decision. It defines the physical realization of the logical isolation that Space has already established. Think of Space as the blueprint for a self-contained room. Runtime is the instruction that tells the compiler whether to build that room inside a larger house or as a separate, detached guest house. The blueprint for the room itself never changes.
CScaf provides two initial Runtime options:
The ThreadGroup Runtime: This instructs the compiler: “Although the BillingSpace is logically independent, for this specific deployment, compile it to run inside the same process as its callers.” Communication becomes a direct, in-memory function call—the fastest possible interaction, with zero network latency or serialization overhead. This is the ideal choice for an MVP, a local development environment, or for a cluster of services that require maximum performance and can be deployed as a single unit. It gives you the performance of a monolith.
The Isolate Runtime: This instructs the compiler: “Now, take that same logical isolation and make it physically real. Compile the BillingSpace to run as a completely separate process.” The compiler then automatically generates all the necessary code to handle network communication, serialization, and discovery. This provides the classic benefits of a microservice: fault isolation (if it crashes, the rest of the system stays up), independent scaling, and independent deployment.
This leads to a truly revolutionary workflow. The combination of Space and Runtime decouples architectural design from deployment topology. You can write your code once, against a safe, logically distributed model. Then, by simply changing a configuration flag—a Runtime declaration—you can completely alter the physical deployment of your system without changing a single line of business logic.
This is the key to a codebase that can truly “grow forever.” A project can start as a high-performance, single-process monolith using the ThreadGroup runtime. As the company grows and certain domains require independent scaling, those specific Spaces can be flipped to the Isolate runtime, peeling them off into microservices one by one, as needed, without a multi-year rewrite project.
By combining these three primitives—Space, Mode, and Runtime—CScaf provides an unprecedented architectural control panel. It empowers the developer to act as a true architect, sculpting the system to meet the precise requirements of logic, performance, and deployment within a single, unified design process.
Finally, for Spaces with different Modes (e.g., Managed and Unmanaged) to cooperate seamlessly, SOP introduces a new, more powerful form of polymorphism: overspace.
In Object-Oriented Programming, polymorphism allows different objects to respond to the same message. An Animal.Speak() message results in a “woof” from a Dog object and a “meow” from a Cat object. It operates on the behavior of objects within a shared environment.
In Structural-Oriented Programming, overspace allows the same logical concept to have completely different physical representations and behaviors depending on the Space it inhabits. It operates on the very structure of an object as it crosses architectural boundaries.
Consider a common concept like a DataBuffer.
Inside a Managed Space, where safety and ease of use are paramount, a DataBuffer might be implemented as a safe, garbage-collected List<byte>. Its methods would be bounds-checked, and memory management would be automatic.
However, when that same logical DataBuffer is passed to an Unmanaged Space for a high-performance video encoding task, its physical representation could become a raw, fixed-size memory block represented by a byte* pointer. Its methods would involve direct memory manipulation for maximum speed.
The key is that the developer interacts with a single, logical DataBuffer concept. The overspace mechanism, enforced by the compiler, handles the transformation. It ensures that when data moves from the Managed world to the Unmanaged world, it is safely and correctly translated from the List<byte> representation into the byte* representation, and vice versa.
Overspace is the bridge that allows a single, unified codebase to safely span the two worlds of “Productivity” and “Performance.” It is the structured, machine-verified mechanism for managing the dangerous transitions that today are handled by manual, error-prone interoperability code. This is a profound concept, and its detailed implementation will be explored in a dedicated future article.
After understanding the philosophy and the foundational architectural concepts of SOP, the next question is: what technical mechanisms allow CScaf to deliver on these bold promises? This part will delve into the two core mechanisms that set CScaf apart: the communication model and the execution model.
In traditional distributed systems, communication between services is one of the greatest sources of error and complexity. CScaf addresses this problem by introducing a new communication primitive, swait, and a completely different contract model.
The Status Quo: Communication between microservices today relies on fixed, pre-defined contracts, typically in the form of gRPC .proto files or OpenAPI specifications.
Why It’s a Problem: This model forces developers to anticipate every possible interaction up front. To avoid the pain of frequent schema changes, these contracts are often designed defensively, with numerous optional fields or generic, all-encompassing structures to hedge against future use cases. This leads to bloated requests that carry excessive data, a phenomenon known as “over-fetching,” where most of the data is irrelevant to the specific task at hand. We are forced to define one contract for all possible scenarios, rather than an optimal contract for the actual scenario taking place. Furthermore, any change, even a minor one, requires a coordinated effort. Updating a single feature can involve a significant amount of work to define a new contract, regenerate code on both the client and server side, and deploy the changes in lockstep. This process, often spanning two different teams, is slow and fraught with the risk of miscommunication and version mismatch errors.
What is swait? A swait block is not just a function call. It is a closure—a block of code, along with its captured environment—that is sent to another Space for execution.
Why do we need it? swait was created to replace fixed, human-defined contracts with dynamic, machine-inferred contracts that are specific to each individual call.
How does it work? When the CScaf compiler encounters a swait block:
It doesn’t just check a method signature. It does something far more intelligent:
It analyzes the entire body of the swait block.
It determines precisely which methods (GetUserProfileAsync, ApplyDiscount, ProcessPayment) are invoked and which variables from the outer scope (order) are captured and used.
Then, it automatically constructs the most optimal request schema possible for this exact scenario. That request payload will contain only the order.UserId and the order object itself. It will carry zero extraneous data.
What is the effect? Each swait call generates a perfectly “tailor-made” request. This completely eliminates the problem of data over-fetching, delivering superior network performance compared to one-size-fits-all API designs.
Theoretically, you can think of the code inside the swait block as still belonging to the calling Space. It is essentially a piece of logic that, at compile time, is packaged up for remote execution. In the language of today’s systems, it’s as if you were writing a normal block of code in Service A whose sole purpose was to intelligently format a DTO before making a gRPC call to Service B and awaiting the result. The revolutionary difference is that in CScaf, the DTO is defined automatically and perfectly for the context, the code block is far more intelligent, and as we will see, it can even operate on “virtual object pointers”—a powerful feature we will introduce later.
The Problem: Passing complex objects over a network is expensive, insecure, and often unnecessary. How does CScaf control this data flow effectively?
The Solution: CScaf introduces a strict and powerful new concept for inter-Space objects. When you obtain a reference to an object from another Space, you are not holding a copy of that object. You are holding a Virtual Object Pointer (VPO)—an opaque handle, a unique system-wide identifier that points to the original object in its home Space. A VPO itself contains zero business data. It is merely a key.
This concept is the foundation for a “secure-by-default” communication model. It prevents the accidental leaking or transmission of massive objects across Space boundaries. To understand how, we must clarify how a swait block actually works.
The code inside a swait block is a form of hybrid code. Most of the logic within the block—loops, conditionals, local variable manipulation—executes in the current, calling Space. It is only when the code makes an explicit call to a function that resides in the target Space that the communication mechanism is triggered.
At that moment, the compiler performs its magic on a very well-defined and limited scope: the parameters of that cross-Space function call.
The compiler statically analyzes the signature of the remote function being called.
It examines the arguments being passed. If an argument is a VPO, it simply sends the lightweight handle across the network.
If an argument is a local object or a primitive value, the compiler automatically generates the minimal DTO required and marshals only that data.
Imagine a swait block with complex local logic and only two calls to functions in another Space. That entire block will result in only two network calls, with two perfectly optimized, auto-generated DTOs. The local logic runs locally. Because the automatic DTO generation is scoped to the static, known signatures of the cross-Space functions, the problem of analyzing an arbitrary block of code is neatly solved.
What is the effect? This creates a model of Intentional Marshalling. Data is only serialized and sent across the wire when the developer makes a conscious, explicit decision to pass it as a parameter to a remote function. This model forces developers to think critically about their service boundaries and what data truly needs to cross them, naturally promoting the design of lean, efficient, and secure APIs.
While the VPO’s role here is to enable this intelligent and secure marshalling, its true revolutionary potential lies in creating an entirely new paradigm for state management in a distributed environment—a topic we will explore in a next chapter.
The true power of the Virtual Object Pointer extends far beyond enabling efficient marshalling. It introduces a paradigm that has been notoriously difficult to achieve in distributed systems: organic, persistent state with minimal cognitive overhead for the developer.
In the traditional microservice world, every interaction is fundamentally stateless from the caller’s perspective. Each API call is a self-contained transaction. To create the illusion of a continuous “session,” developers are forced to build complex and brittle workarounds: caching layers, sticky session logic in load balancers, or manually passing context IDs and tokens back and forth with every single request. Attempts to solve this inside a single service with patterns like the Singleton are clumsy, process-bound, and do not translate to a distributed environment. The burden of state management falls squarely on the developer.
VPOs liberate the developer from this burden. When an object from one Space is passed into another for the first time, CScaf can implicitly “pin” that object’s context within the receiving Space. The VPO held by the caller becomes more than just a pointer; it becomes a key to a living, stateful session on the remote system.
Let’s revisit our Billing example to see this in action. The original code was a single, monolithic transaction. Now, let’s break it into a more realistic, multi-step workflow.
var user = new User() { Id = (UUID) “i-know-it-not-uuid” }; var order = new Order(){ UserId = user.Id }; var finalPrice = swait Billing { // Example about overspace and why it safe even in multi-space. // All getter will in current space and all setter is in target space. user.Id = (byte[]) user.Id.ToBytes(); order.UserId = (string) order.UserId; user.GetUserProfile(order.UserId); if (user.Profile.IsPremium) { ApplyDiscount(order, 0.1m); } // Example about self maintain cross space VPO data. user.Destroy(); return order.finalPrice; } // Fire-and-forget. // srun is swait but not return anything. srun Log { Logging($”Final price is: {finalPrice}.”); } srun Billing { var statusCode = order.ProcessPayment(); // or ProcessPayment(order); if you define ProcessPayment like a endpoint. // Example about swait inside swait srun Log { // Getter and setter source value is update in this scope. // This time all variable before srun is the getter Logging($”Status code: {statusCode}”); } // Don’t have any destroy here because the destroy could be done in ProcessPayment if you want. }This is a profound shift. The developer in the ApiGateway Space did not have to manage any state. They simply used the same object variable in two separate calls. The Billing Space, however, was able to maintain a continuous, stateful context. The complex dance of passing session tokens or context IDs is completely abstracted away by the VPO and the CScaf runtime. This enables a far more natural and organic data lifecycle, allowing developers to design complex, multi-step sagas as if they were simple, local function calls.
As a challenge to the reader, consider for a moment what it would take to replicate this exact showcase using today’s languages and tools. You would begin by defining the DTOs and service contracts for at least two separate API endpoints. Then, you would need to architect a state management strategy for the Billing service—perhaps a Redis cache or a temporary database entry, keyed by a transaction ID. You’d have to write the logic in the ApiGateway to make the first call, receive the transaction ID, and then remember to pass that ID along with the second call. You’d need boilerplate for HttpClient, serialization, and error handling for every interaction. You would need to build an entire web of incidental complexity, all to orchestrate what, in CScaf, is expressed as a few simple, sequential lines of code.
The Problem: Current protocols like gRPC/Protobuf are powerful, but they are built on fixed, human-defined schemas. Even in the most efficient binary formats, they must still transmit metadata—such as the names or numerical tags of fields—so the receiving end can interpret the data. This creates a small but persistent overhead on every single call.
The Opportunity: Because the CScaf compiler can analyze the code inside every unique swait block, it possesses a perfect, synchronized understanding of both sides of the communication. It doesn’t just know which method is being called; it knows the exact structure and byte-by-byte order of the data that needs to be sent.
The Solution: CScaf leverages this unique opportunity by introducing an automatic binary protocol: SpaceWire. Instead of using a fixed, global schema, SpaceWire revolutionizes serialization:
At compile time, for each unique swait call site, the compiler generates a rigid and absolutely minimal “serialization contract.” This contract has no field names and no tags; it is simply an agreed-upon byte order.
For example, the contract might dictate: “The first 4 bytes are an int32 for userId, the next 8 bytes are a double for price, and the remainder is a UTF-8 string whose length is defined by the preceding 2 bytes.”
When a Virtual Object Pointer (VPO) is passed, the contract becomes even simpler and more efficient. It might just say: “The next 16 bytes are the UUID that represents this VPO.”
The code to read and write data according to this exact contract is auto-generated for both the sender and the receiver by the same compiler.
Why is This Model Viable and Safe?
Because it is a hard, machine-enforced convention, not a soft, verbal agreement.
Both sides of the communication are born from the same single source of truth (the CScaf code) and the same tool (the compiler).
The possibility of a mismatch error becomes nearly zero, because if there is any change to the data structures involved in the call, the entire project will fail to compile until both sides have their communication code regenerated.
What is the effect?
Maximum Performance: SpaceWire is capable of producing theoretically minimal payloads. It eliminates nearly all metadata overhead, transmitting only the raw data essential for the call. This is critically important for high-throughput systems.
Maximum Productivity: The developer never has to think about serialization. This entire complex process is completely transparent and fully automated, allowing them to focus exclusively on business logic.
Our current languages have created an artificial and painful dichotomy between “synchronous” (sync) and “asynchronous” (async) code. We are forced to “color” our functions with the async keyword, creating two distinct worlds of functions. The interaction between these two worlds is a notorious source of complex bugs, most famously the dreaded “sync-over-async” deadlock.
This divide stems from a fundamental misunderstanding, an artifact of our history. The problem isn’t sequential execution itself. The problem is that our entire model of sequential execution is rooted in the primal assumption of a single computer with a single core. In that world, everything was synchronous.
As soon as we introduced more than one thread, the concept of asynchronicity was born, but it has always been treated as a special case, an add-on. No mainstream language has ever elevated asynchronous, multi-threaded execution to be the primary, default model. It has always been an opt-in complexity.
Now, in the world of distributed Spaces, this model is no longer tenable. Asynchronicity is not a special case; it is a mandatory, physical reality.
Sequential thinking, at a small scale, is natural and essential. When a developer writes the logic inside a single function, they are thinking sequentially: do step A, then step B, then step C. This is a powerful and clear mental model. Even inside a modern C# async method, the code between await points still executes sequentially.
The real problem arises when we try to impose that small-scale sequential assumption at the macro scale, especially when function calls cross logical and physical boundaries.
CScaf resolves this problem not by eliminating synchronous execution, but by putting it in its proper place. The philosophy of CScaf is:
Sequential execution is the default at the micro level (inside a function body).
Asynchronous execution is the default at the macro level (between function interactions).
CScaf will completely eliminate both the async and sync keywords. Instead, the execution model is inferred naturally from the structure of the code itself:
The Function Body is Sequential:
Inside the body of a function, lines of code execute in top-to-bottom order, just as a programmer would expect. The simplicity and clarity of sequential code is completely preserved at the smallest scale.
Every Function Call is Asynchronous:
This is the conceptual leap. In CScaf, any call to another function (AnotherFunction()) is non-blocking. It conceptually returns a “future” or a “promise” of a result immediately.
Why? Because CScaf makes no assumptions about where AnotherFunction() resides. It could be in the same Space, or it could be on a server across the planet. By treating every function call as asynchronous by default, CScaf creates a single, consistent model for both local and distributed code.
The await (or swait) Keyword is the Bridge:
How do we get the actual result from that “promise”? By using a single keyword to synchronize: await (or swait for cross-Space calls to clarify architectural intent).
await is not what “turns on” async mode. await is what pauses the sequential execution of the current function body to wait for the result of another asynchronous operation to complete.
It is critical to understand that the sequential nature of a function body is a powerful, high-level abstraction—an illusion crafted for the developer. Under the hood, the entire CScaf runtime would be built on a foundation of controlled, hybrid asynchronicity.
Think of it this way: everything is fundamentally asynchronous, but the developer works as if it were synchronous. The program executes as if it were sequential, but with one key difference: the runtime itself is free to insert invisible await points. For example, when one function calls another within the same thread, the runtime might execute it synchronously for performance. But if that call requires accessing a resource that could block, or if the system is under heavy load, the runtime could transparently treat it as an asynchronous yield point, freeing up the thread to do other work.
The developer is shielded from this complexity. They write clear, sequential logic, and the runtime handles the sophisticated task of scheduling that logic in the most efficient, non-blocking way possible.
Eliminates Classic Bugs: This model makes the “sync-over-async” deadlock syntactically impossible. There is no way to blindly “block” for a result (like calling .Result or .Wait()); you can only safely “await” it.
A More Natural Mental Model: Developers no longer need to “color” their functions with async. They simply write code naturally. The sequential flow within a function is preserved, and asynchronicity appears only where it’s logically needed: at the interaction points between functions.
Seamless Scalability: The model makes no fundamental distinction between calling a function in the same process and calling one in a different process. This is what allows a CScaf codebase to be “stretched” from a ThreadGroup monolith into an Isolate microservice system without changing the programming model or the business logic.
This is a deliberate paradigm shift. Because the underlying runtime is an asynchronous fortress, developers cannot continue to think in the old, strictly synchronous way. Yet, this new model doesn’t completely upend their intuition. It simply asks them to remember one new rule: although the code looks sequential, the runtime may introduce non-blocking waits whenever necessary—even, in theory, during a variable assignment if it involved a remote resource.
Naturally, this “everything is potentially async” model raises questions about performance. The overhead of a “ghost async” operation, however small, might not be acceptable for all use cases. This is where the architectural primitives become critical. The Mode property of a Space could allow a developer to opt into a “full-sync” execution mode for performance-critical code, disabling the runtime’s scheduling flexibility in favor of raw speed. Furthermore, it opens the door for future runtime innovations that can intelligently hybridize true synchronous execution with ghost asynchronicity, making the optimal choice on a per-call basis.
In this way, CScaf does not force the developer to abandon the simplicity of sequential thinking. Instead, it places that thinking inside safe “boxes” (function bodies) and then provides a consistent, safe, and asynchronous mechanism to connect those boxes into a larger system, while still offering the escape hatches needed for ultimate performance tuning.
The mechanisms and philosophies we have discussed—Space, Mode, Runtime, swait, and the VPO—are not isolated technical improvements. They are the foundational pillars of a completely new development experience, one designed from first principles to conquer the chaos of large-scale systems.
To appreciate this future, we must first acknowledge the present. We live in a “microservice archipelago”: a sea of hundreds of isolated repositories. To implement a single cross-cutting feature, a developer must become an archaeologist, digging through wikis and stale documentation to map the dependencies. Their IDE, the most powerful tool in their arsenal, is rendered nearly useless, its “Go to Definition” capability halting at the dead end of an opaque HTTP call. This is not a failure of our engineers; it is a direct and predictable failure of tools born from the “One Computer” assumption, forcing the creation of the massive, complex tooling ecosystem we now struggle to maintain.
This is why industry giants invest billions in monorepo systems like Piper. They understand a fundamental truth: a unified codebase is a tremendous advantage for managing complexity, even if the deployment targets are distributed.
CScaf and Structural-Oriented Programming take this philosophy to its logical conclusion. It’s not merely about putting all the code in one place; the revolution is to make the language and the compiler themselves aware of the entire system architecture.
Imagine this world:
A developer interacts with a single, logical codebase. The IDE is no longer blind; it sees the whole system. The conceptual boundaries between Spaces, enforced at runtime, become transparent to the developer’s tools. Navigating a swait call is as seamless as a local function call. The full impact of a change is visible at compile time, not discovered during a production outage. Refactoring a core concept shared across the system is no longer an act of fear, but a safe, automated operation, whose correctness is guaranteed by the compiler across the entire distributed system.
This is the world that Virtual Object Pointers make possible, where state can be managed organically across services. This is the flexibility that the Runtime primitive provides, allowing this unified experience to exist whether the system is compiled to a monolith or to microservices. This is the safety that machine-enforced contracts provide, turning the compiler into the ultimate guardian of architectural integrity.
This is not a distant dream. It is the promise of restoring clarity, of dissolving the incidental complexity that has consumed our industry, and of giving developers back the superpowers needed to manage the essential complexity of the problems we are trying to solve.
This manifesto has traced a long journey, from the deep fissures in the foundations of modern programming to the outline of a new model—Structural-Oriented Programming—and its initial realization in CScaf.
I have argued that the problems of codebase fragmentation, the false trade-off between productivity and performance, and the crushing complexity of distributed systems are not inevitable. They are symptoms of tools designed for a bygone era.
CScaf is my proposed hypothesis: that by integrating architecture directly into the language, by embracing asynchronicity as the default, and by providing machine-enforced contracts, we can create a new generation of applications—systems that can grow naturally and sustainably from a simple seed into a towering tree.
This is an ambitious vision. But this is no longer just a vision.
The philosophical framework for this system is complete. The detailed design for a Minimum Viable Product—the first bridge to this new world—is already written. My immediate task is to translate these extensive design documents into English, and they will be made public soon.
This is where the journey truly begins, and it cannot be a solo one. I am actively seeking not just collaborators, but critical thinkers. Constructive criticism, dissenting opinions, and messages of support are all equally vital to forging these ideas into a robust reality. The strength of this project will be determined by the rigor of the debate that surrounds it.
If you like me, believe there is a better way to build software—that we can and must demand more from our tools—then I invite you to engage with this project. Follow the repository, read the upcoming design documents, and join the conversation. The foundation has been laid, and the future is now waiting to be built.