
Executive Brief
A software developer published a technical proposal on February 17, 2025, arguing that Rust's macro system can serve as a replacement for Google's Protocol Buffers (Protobuf) when defining cross-language interfaces. The approach combines three existing Rust ecosystem tools: serde for serialization, wasm-bindgen for JavaScript bindings, and pyo3 for Python bindings.
The developer, known as Creston, released a proof-of-concept library called "ridl" (pronounced "riddle") on GitHub to demonstrate the concept. The repository, created on February 16, 2025, describes itself as "a multi-lingual interface description language built from Rust macros."
Protobuf, developed by Google, has long served as a standard for defining data structures that can be serialized and shared across different programming languages. The format requires developers to write interface definitions in a separate .proto file, which is then compiled by the protoc tool into language-specific code.
The ridl approach eliminates the separate interface definition language by using Rust structs directly. Developers annotate their Rust types with macros that automatically generate bindings for other languages. At the time of publication, the library supported Python and JavaScript through WebAssembly.
The proposal addresses several criticisms of Protobuf, including its verbosity when representing complex data types and the friction of maintaining separate interface definition files. However, the approach requires all interface definitions to originate in Rust, which may limit adoption in projects where Rust is not the primary language.
What Happened
On February 16, 2025, developer Creston created a public GitHub repository for a library called ridl. The following day, February 17, 2025, Creston published a detailed blog post explaining the technical rationale and implementation approach.
The blog post outlined the core premise: Rust's macro system, combined with existing serialization and foreign function interface libraries, can provide the same cross-language interoperability that Protobuf offers. The author cited the "long tradition of replacing things with Rust," referencing projects like Astral (Python tooling), rspack (JavaScript bundler), ripgrep (search tool), RustPython (Python interpreter), and nushell (shell).
According to the blog post, the ridl library uses three key Rust ecosystem components. Serde, described as the 10th most downloaded crate on crates.io, provides format-agnostic serialization. The wasm-bindgen macro generates JavaScript bindings through WebAssembly. The pyo3 macro generates Python bindings through the Python C API.
The repository was published under the MIT license and contained example code demonstrating a web server that exposes Rust types to both Python and JavaScript clients.

Key Claims and Evidence
The blog post made several technical claims about Protobuf's limitations. According to the author, Protobuf's interface description language is "extremely limited in its expressiveness" when representing complex data structures. The post cited the need for Google to publish a separate Python library called proto-plus-python to address ergonomic issues in generated Python code.
The author provided a specific example comparing Protobuf and Rust representations of arithmetic expressions. In Protobuf, representing a binary operation required separate message types for BinaryOp and UnaryOp, along with a wrapper message using oneof. In Rust, the same concept could be expressed with a single enum type using nested variants.
Regarding serde, the blog post stated that the library allows developers to "delay the choice of format all the way until the moment we absolutely need it." The author noted that serde supports multiple serialization formats including JSON and MessagePack, allowing developers to switch formats without changing their type definitions.
The ridl library's GitHub description confirmed its purpose as "a multi-lingual interface description language built from Rust macros." The repository showed the project was written entirely in Rust and had received 2 stars as of the publication date.
Pros and Opportunities
The proposed approach offers several potential advantages for development teams already using Rust. By defining interfaces in Rust rather than a separate IDL, developers can use Rust's full type system, including enums with associated data, generics, and trait bounds. The author argued this provides "more flexible types" that "make it easier to express what we mean in our APIs."
Serde's format-agnostic design allows the same type definitions to serialize to different formats. According to the serde documentation, developers can "plug-and-play any serialization format" without modifying their struct definitions. The blog post suggested this could enable using JSON during development and switching to MessagePack for production performance.
The approach eliminates the need for the protoc compiler and separate .proto files. For projects where Rust is the primary language, this reduces the number of tools in the build pipeline and keeps all type definitions in a single language.
Teams building WebAssembly applications or Python extensions from Rust code could benefit from unified type definitions. The same Rust struct could serve as the internal data model, the serialization format, and the foreign language binding.

Cons, Risks, and Limitations
The ridl approach requires Rust to be the source of truth for all interface definitions. Projects where Rust is not the primary language, or where multiple teams work in different languages, would need to adopt Rust specifically for interface definitions. The author acknowledged this limitation, stating the library "serves as a proof-of-concept" rather than a production-ready solution.
Protobuf's ecosystem includes mature tooling for schema evolution, backward compatibility checking, and documentation generation. The ridl library, as a newly published proof-of-concept, lacks these features. The GitHub repository showed no releases, no documentation beyond the README, and minimal community adoption at the time of publication.
The approach relies on WebAssembly for JavaScript bindings, which introduces runtime overhead compared to native JavaScript objects. Applications with strict performance requirements may find this trade-off unacceptable.
Serde, while widely used in the Rust ecosystem, does not guarantee wire-format compatibility with Protobuf. Teams migrating from Protobuf would need to ensure their serialization format choice maintains compatibility with existing systems.
The blog post did not address gRPC integration. Protobuf serves as the default serialization format for gRPC, and replacing Protobuf would require alternative approaches for RPC communication.
How the Technology Works
The ridl library combines three Rust macro systems to achieve cross-language interoperability. At the core, developers define their data types as standard Rust structs and enums. These types are annotated with derive macros that generate additional code at compile time.
Serde provides the Serialize and Deserialize derive macros. When applied to a struct, these macros generate implementations that can convert the struct to and from various formats. The format is determined at the point of serialization, not at the type definition. A struct annotated with serde derives can be serialized to JSON, MessagePack, CBOR, or any other format with a serde-compatible serializer.
The wasm-bindgen macro generates WebAssembly bindings that expose Rust types to JavaScript. When a Rust library is compiled to WebAssembly with wasm-bindgen annotations, the resulting module includes JavaScript wrapper code that handles type conversion between JavaScript objects and Rust memory.
The pyo3 macro generates Python bindings through the Python C API. Rust structs annotated with pyo3 macros become Python classes when the library is compiled as a Python extension module. The generated code handles memory management and type conversion between Python objects and Rust values.
In ridl, these three systems are combined through conditional compilation. The library defines custom macros (popo for Python and pojso for JavaScript) that wrap the underlying pyo3 and wasm-bindgen macros. Developers annotate their types once, and the appropriate bindings are generated based on compile-time feature flags.
Technical context (optional): The approach leverages Rust's procedural macro system, which allows arbitrary code generation at compile time. Unlike C preprocessor macros, Rust procedural macros operate on the abstract syntax tree and can generate type-safe code. The serde library uses this capability to generate serialization code that is specialized for each struct's field types, avoiding runtime reflection overhead.
Broader Industry Implications
The proposal reflects ongoing interest in Rust as a systems programming language that can interface with higher-level languages. Projects like PyO3 and wasm-bindgen have matured to the point where Rust libraries can be consumed from Python and JavaScript with minimal friction.
The criticism of Protobuf's expressiveness echoes discussions in the broader developer community. Alternative serialization formats and IDLs, including Cap'n Proto, FlatBuffers, and Apache Thrift, have emerged to address various Protobuf limitations. The ridl approach represents a different strategy: rather than creating a new IDL, it proposes using an existing general-purpose language.
The "rewrite it in Rust" pattern has produced several successful projects in recent years. Tools like ripgrep, fd, and bat have demonstrated that Rust implementations can match or exceed the performance of C implementations while providing memory safety guarantees. The ridl proposal extends this pattern to the domain of interface definition.
For organizations evaluating Rust adoption, the ability to define interfaces in Rust and expose them to existing Python or JavaScript codebases could reduce migration friction. However, this benefit depends on Rust being a strategic language choice rather than a tactical one.
What Is Confirmed vs. What Remains Unclear
Confirmed:
- The ridl repository exists on GitHub under the MIT license
- The repository was created on February 16, 2025
- The library uses serde, wasm-bindgen, and pyo3 as dependencies
- The blog post was published on February 17, 2025
- The library supports Python and JavaScript bindings
Unclear:
- Performance characteristics compared to native Protobuf implementations
- Schema evolution and backward compatibility strategies
- Plans for supporting additional languages beyond Python and JavaScript
- Whether the author intends to develop ridl beyond proof-of-concept stage
- Community interest and adoption trajectory
What to Watch Next
The ridl repository's GitHub activity will indicate whether the project gains traction. Stars, forks, and pull requests would signal community interest in the approach.
Discussions in Rust community forums, including the Rust subreddit and users.rust-lang.org, may reveal developer sentiment toward using Rust as an IDL replacement.
Updates to the serde, wasm-bindgen, or pyo3 libraries could affect ridl's viability. Changes to these foundational libraries' APIs or capabilities would directly impact the approach.
Responses from the Protobuf team or broader serialization community could provide perspective on the proposal's technical merits and limitations.
Sources
- creston.blog - "Rust can replace Protobuf" - February 17, 2025 - https://creston.blog/rust-can-replace-protobuf/
- GitHub - crestonbunch/ridl - Created February 16, 2025 - https://github.com/crestonbunch/ridl
- Serde - Rust Serialization Framework - https://serde.rs/



