Multi-Language Strategy#
APX provides a symmetric developer experience across languages. The core principle: schemas are the published artifact, not generated stubs. Code is always generated locally using each language’s native toolchain and packaging conventions.
Design Principles#
Schema-first publishing – APX releases schema files (
.proto, OpenAPI specs, Avro schemas) to a canonical repository or artifact registry. Generated code is never published.Local generation – Every consumer generates code locally. This gives teams control over toolchain versions (protoc, grpc, etc.) and avoids version coupling between producer and consumer.
Same identity everywhere – The same API identity (
proto/payments/ledger/v1) deterministically derives coordinates for every language. Dev and prod use the same identity; only the resolution backend changes.Native packaging – Each language uses its own ecosystem’s conventions. Go developers see Go modules, Python developers see pip packages, Java developers see Maven coordinates.
Language Support Matrix#
Language |
Artifact |
Local Overlay |
Resolution |
Codegen |
Dev Command |
Unlink Hint |
Tier |
|---|---|---|---|---|---|---|---|
Go |
Go module |
|
go.work -> go.mod |
|
|
|
Tier 1 |
Cpp |
Conan package |
|
Conan dependency |
|
|
Update |
Tier 2 |
Java |
Maven JAR |
|
Maven dependency |
protobuf-maven-plugin |
|
Update |
Tier 2 |
Python |
Python wheel |
|
pkgutil namespace |
|
|
|
Tier 2 |
Rust |
Cargo crate |
|
Cargo dependency |
|
|
Update |
Tier 2 |
Typescript |
npm package |
|
npm/yarn |
protoc + ts-proto |
|
|
Tier 2 |
Tier definitions#
Tier 1 – Full overlay lifecycle: generate, sync, link, unlink, release. First-class CI support.
Tier 2 – Identity derivation, generation, and local development. Release and CI support in progress.
Planned – Identity derivation designed but not yet implemented.
Identity Derivation by Language#
Given org=acme and API path proto/payments/ledger/v1:
Coordinate |
Derived Value |
|---|---|
Go module |
|
Go import |
|
Conan |
|
C++ ns |
|
Maven |
|
Java pkg |
|
Py dist |
|
Py import |
|
Crate |
|
Rust mod |
|
npm |
|
Go Workflow#
Go is the Tier 1 language with the most mature overlay system:
apx gen gogenerates code intointernal/gen/go/with a synthesizedgo.moddeclaring the canonical module path.apx syncaddsusedirectives togo.workso the Go toolchain resolves canonical imports to local overlays.When ready for production,
apx unlinkremoves the overlay andgo getadds the released module. Import paths stay the same.
Python Workflow#
Python uses editable installs (pip install -e) as the local resolution mechanism:
apx gen pythonscaffolds each overlay as an installable Python package withpyproject.tomland namespace__init__.pyfiles.apx link pythonrunspip install -efor each overlay into the active virtualenv.apx unlinkremoves the overlay;pip install <dist-name>adds the released package. Import paths stay the same.
Java Workflow (Maven-Native)#
Java uses Maven’s dependency resolution and code generation phases:
Producer releases schema artifacts (proto files packaged as a jar/zip) to a Maven repository via APX’s release pipeline.
Consumer adds the schema artifact as a Maven dependency using the derived coordinates (
com.<org>.apis:<domain>-<name>-<line>-proto).Maven’s
generate-sourcesphase usesprotobuf-maven-plugin(or equivalent) to generate Java code from the schema artifact intotarget/generated-sources/.For local development,
apx link java(planned) installs schema artifacts to~/.m2/repository, allowing Maven to resolve them without a remote repository.
Java developers never interact with Go modules or go.work. The Maven coordinate system provides a complete, self-contained experience.
TypeScript Workflow#
TypeScript uses npm packages as the published artifact with scoped package names:
Producer releases schema artifacts to an npm registry via APX’s release pipeline. The npm package name is deterministically derived:
@<org>/<domain>-<name>-<line>-proto.Consumer installs the package using
npm install @<org>/<domain>-<name>-<line>-proto.For local development,
apx link typescript(planned) links local schema artifacts vianpm link, allowing resolution without a remote registry.apx unlinkremoves the local link;npm install @<org>/<pkg>adds the released package. Import paths stay the same.
TypeScript developers import generated types directly from the npm package name:
import { LedgerService } from "@acme/payments-ledger-v1-proto";