Skip to main contentSkip to main navigationSkip to footer
JZdev
ProjectsBlogContact
es/en
es/en
JZ
Navigation menu
ProjectsBlogContact
JZ

Backend Developer specialized in end-to-end systems with Java, Go and Rust — robust, scalable and maintainable solutions.

Get in touch →

Navigation

  • Projects
  • Blog
  • Contact
© 2026 Javier Zader. Made withand lots of mate 🧉
PrivacyGDPR DataBuilt with Next.js
Home/Projects/APiGen
Back to projects
CuratedFeatured

APiGen

A code-generation platform: from a SQL schema or an OpenAPI contract to a backend service that compiles —not a scaffold, a production-shaped service you keep owning afterward.

View origin

About this project

Creating a CRUD service in Spring Boot is always the same path: the entity, the repository, the service, the controller, the DTOs, the security setup, the observability wiring. It is mechanical work, and when it repeats across teams, each service ends up with slightly different conventions. That divergence is expensive to reverse later.

apigen takes a SQL schema or an OpenAPI contract and generates that whole service: persistence, security, observability, Dockerfile, Kubernetes manifests, CI. The difference from a scaffolder is that the output stays editable —you can override templates without forking, and preview before generating.

It generates for 12 language/framework combinations. Nine of them go through a CI job that compiles the generated project with each language's native toolchain (go build, cargo check, dotnet build, tsc) instead of comparing against expected strings. That distinction matters: a green golden test does not guarantee the code compiles.

At a glance#

  • ~510,000 lines of Java across 24 Gradle modules, 8,406 tests
  • 12 language/framework targets; 9 with a native compile gate in CI
  • 9 database dialects; deploys to 4 clouds (AWS, Azure, GCP, DigitalOcean) via Terraform
  • 458 merged pull requests over ~5.5 months
Loading diagram...
The example schema (14 tables) apigen consumes in the hero demo — relationships taken from the repo's real examples/ecommerce-schema.sql. coupons doesn't show up: it has no FKs (the coupon is resolved by code).

Constraints I Set#

  • Contract-first only. Source of truth is the SQL schema or OpenAPI file. No config DSL layered on top.
  • Generated code must compile and pass tests on the first try. No scaffolding that needs manual fixing.
  • Customizations live next to the project in .apigen/templates. Not in a fork.
  • One engine, every interface. CLI, server, IDE plugin, and MCP all consume the same generation core. No duplication.

My Role#

Single developer. Started December 2024 as a generic Spring Boot REST library. Designed every module, wrote every line that was not auto-generated. Java/Spring background gave me the opinion to encode; APiGen is the platform around that opinion.

How APiGen Started, And Why It Grew#

APiGen began in December 2024 as a generic Spring Boot REST library — the linked repository above. The original code is a base-controller / base-service / base-repository pattern with generics, Hibernate Envers auditing, ModelMapper conversion, centralized exception handling, and pagination, on Spring Boot 3 and Java 21.

The goal was modest: encode my preferred conventions so I would stop rewriting the same controllers, the same security setup, the same exception handlers across services.

As the library matured through 2025, the question shifted. If the conventions are encoded, why does the user have to write the entities at all? Why not generate them from the schema? Then: if the engine can generate Java/Spring, why not Kotlin? Python? Go?

By January 2026 the project became a full code generation platform — the version described in the rest of this page. The link above points to the original generic library so the starting point is verifiable; the platform that grew from it is not public.

Key Decisions#

1. Decoupled pipeline: parsing → IR → template rendering#

The most consequential early decision. Parsers (SQL, OpenAPI) produce a normalized intermediate representation. Templates consume the IR. Neither side knows the other exists.

That separation is what made 12 target languages thinkable. Adding Kotlin does not touch the SQL parser. Adding GraphQL does not touch the codegen pipeline.

Tradeoff: the IR is rigid by design. There is no shortcut from "this OpenAPI quirk" straight to "this Java annotation". Every shortcut has to round-trip through the IR, or the abstraction stops paying off.

Loading diagram...
Parsers and templates don't know about each other: everything goes through the IR. That's why adding a language doesn't touch the SQL parser, and adding a protocol doesn't touch the codegen pipeline.
Loading diagram...
The same pipeline at runtime: an end-to-end `apigen generate`, from schema to 199 files that boot. This is the real run from the hero terminal.

2. Features as opt-in Gradle modules#

APiGen ships 22 modules: 4 libraries, 4 generators, 13 feature packs (gateway, GraphQL, gRPC, chaos engineering, recommendation, analytics, BFF, notifications, search, observability, and more), and an MCP layer.

Features are not always-on flags. They are separate modules a project opts into. A team that needs gRPC includes the gRPC pack; a team that does not gets nothing extra in their build. Each pack versions independently — the chaos pack can move forward without touching the gateway pack.

Tradeoff: module-boundary discipline. Every feature pack pays a small overhead in setup and contract maintenance. Letting features bleed into core would have made the early experience faster — and the cleanup later much worse.

3. One engine, four delivery surfaces#

The same codegen engine runs behind a CLI (local generation, preview, validation), an HTTP server (preview endpoints, team-shared flows), an IDE plugin (in-editor authoring), and an MCP server (AI assistants drive generation as a tool).

Choosing this on day one forced the engine to be library-shaped from the start, not a CLI with an API bolted on later. That made the MCP integration almost free when it landed.

Loading diagram...
The same engine behind all four surfaces. Because it was library-shaped from day one, wiring up MCP was almost free.

What APiGen Can Do Today#

  • 12 language/framework targets — Java/Spring, Kotlin, Python, Node/TypeScript, Go, Rust, C#, PHP, Ruby, Scala, Elixir, Clojure.
  • 9 database dialects supported — PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, SQLite, MongoDB, Cassandra, Redis.
  • REST, GraphQL and gRPC from the same model — no logic duplication across protocols.
  • Enterprise features built in by default: soft delete, multi-tenancy, Hibernate Envers auditing, optimistic locking, GDPR/SOC2/PCI compliance reports — 100+ across modules.
  • Multi-level cache out of the box: Caffeine (in-process) + Redis (distributed), with cache-aside policies generated per entity.
  • 4 cloud targets — AWS, Azure, GCP, DigitalOcean, with Terraform output.
  • 60% line / 50% branch coverage minimum, gated in CI.
  • Contract tests (Spring Cloud Contract) on the core library + JMH microbenchmarks on the generation engine.
Loading diagram...
A single model, derived from the IR, exposes all three protocols — without rewriting business logic.

What I'd Reconsider#

Growing breadth-first. APiGen scaled outward fast — 12 language/framework targets, 9 database dialects, 13 feature packs — while Java/Spring is the only target where I have full operational confidence. The platform looks comprehensive on paper, but a user landing on Elixir or Clojure gets a less mature path than a user landing on Java.

If I started over, I would compress the matrix. Two languages (Java + Python, or Java + Kotlin) and three databases (Postgres, MySQL, Mongo) deep before any breadth growth. "Supports 12 languages" sells better than "supports 2" — but engineering reputation matters more than marketing.

Architecture Snapshot#

22 Gradle modules organized in 4 layers:

  • libs/ — core (engine + IR), security, exceptions, bom (shared dependency catalog).
  • generator/ — cli, codegen, server, ide-plugins.
  • features/ — 13 opt-in packs (graphql, grpc, gateway, chaos, recommendation, analytics, bff, notifications, search, observability, and more).
  • mcp/ — Java + Python MCP servers exposing the engine to AI assistants.
  • Container variants: standard Dockerfile + Dockerfile.native for GraalVM native-image compilation when startup time and memory footprint matter.

The build graph stays clean because the contract is enforced by the shared BOM plus separation of API and implementation modules. No cycles, no shared mutable state across modules.

Loading diagram...
22 modules in 4 layers. generator/ depends on core+IR; the feature packs plug into codegen without touching the core; the BOM governs versions. No cycles.

Technologies

JavaSpring BootGraphQLgRPCOpenAPIMCPDockerKubernetesTerraformGradle

Details

Source:Curated
Status:Featured

Links

Origin repository

Want to work together?

Let's talk about your next project, or dig deeper into my experience.

Get in touchDownload CV