How Palmyra compares#
An honest side-by-side with the frameworks teams typically evaluate alongside Palmyra. Every tool has a sweet spot; the goal here is to help you decide, not to sell.
Palmyra’s frontend works with any backend. Implement a custom
StoreFactoryand the same grids, forms, and lookups talk to REST, GraphQL, Firebase, or any legacy API — no component changes needed. See Connecting to a custom backend.
Backend comparisons#
vs Spring Data REST#
Spring Data REST auto-publishes JPA repositories as REST endpoints — conceptually the closest alternative.
| Palmyra advantage | Spring Data REST advantage | |
|---|---|---|
| Query flexibility | Client picks fields, filters, sort, and pagination via query params; server compiles the SQL | HAL/JSON-API-standard hypermedia out of the box |
| Performance | Raw JDBC under the hood — no Hibernate session, no lazy-loading surprises; sub-50 ms typical | Leverages full JPA/Hibernate ecosystem (caching, dirty-check, cascades) |
| Lifecycle hooks | Fine-grained: preCreate, onUpdate, applyQueryFilter, onQueryResult — per handler |
Event-based (@HandleBeforeSave, @HandleAfterCreate) — broader but less granular |
| Export | CsvHandler / ExcelHandler stream reactively out of the box |
No built-in export — add a custom controller |
| Frontend | Ships a matching React component library (Mantine + MUI) | Frontend-agnostic — bring your own |
| Community | Smaller; documentation is this site | Massive Spring ecosystem; extensive third-party tutorials |
| Schema flexibility | @PalmyraMappingConfig lets you declare FK/UK in code when DB doesn’t have them |
Relies on JPA metadata — if it’s not in the entity, it doesn’t exist |
Pick Palmyra when you want client-driven queries + raw JDBC speed + an integrated React layer. Pick Spring Data REST when you need hypermedia, Hibernate’s full ORM surface, or the Spring ecosystem’s breadth.
vs JHipster#
JHipster generates a full-stack app (Spring Boot + Angular/React/Vue) from a domain model DSL.
| Palmyra advantage | JHipster advantage | |
|---|---|---|
| Philosophy | Runtime-driven — no code generation, no regeneration drift | One-command scaffold with CI/CD, Docker, monitoring, microservices |
| Incremental adoption | Add one dependency to an existing SpringBoot project | Designed to own the whole project from day one |
| Entity changes | Edit the POJO, restart — done | Re-run the generator, resolve merge conflicts |
| Frontend flexibility | Swap Mantine ↔ MUI; compose your own pages | Generated screens are opinionated — customising means editing generated code |
| Learning curve | Learn annotations + handler interfaces | Learn JDL (domain language) + the generated project structure |
| Production scaffolding | You bring your own CI/CD, Docker, monitoring | Ships with Prometheus, ELK, Docker Compose, Kubernetes configs |
| Microservices | Not in scope — Palmyra is a library, not an architecture | First-class microservice/gateway support |
Pick Palmyra when you have an existing SpringBoot project or want to stay closer to plain Java code. Pick JHipster when you’re greenfield, want an opinionated full-stack generator, and need microservice scaffolding.
vs Hasura / PostgREST#
Auto-generated APIs from a PostgreSQL schema — no Java, no SpringBoot.
| Palmyra advantage | Hasura / PostgREST advantage | |
|---|---|---|
| Language / stack | Java / SpringBoot — fits teams that already run JVM services | Zero backend code; configure via dashboard or YAML |
| Business logic | Handler lifecycle hooks (Java) — arbitrary complexity | Hasura Actions / PostgREST functions — limited to SQL or a sidecar service |
| Multi-database | MariaDB, MySQL, PostgreSQL, Oracle, DB2 | PostgreSQL only (Hasura adds some others with Enterprise) |
| Frontend | Ships matched React components | Frontend-agnostic (GraphQL clients everywhere) |
| Client query shape | REST with query params | GraphQL — richer query language, subscriptions |
| Deployment | Standard Spring Boot .jar — runs anywhere Java runs |
Separate containerised service; Hasura Cloud for managed |
| Joins | Declared via annotations or DB metadata; dotted-path filters auto-join | Auto-discovered from FK constraints; GraphQL nested queries |
Pick Palmyra when you need Java business logic, multiple DB vendors, or a matched frontend layer. Pick Hasura / PostgREST when you want zero backend code, PostgreSQL is your only DB, and GraphQL is the API shape you need.
vs plain Spring @RestController#
No framework beyond Spring Boot itself.
| Palmyra advantage | Plain Spring advantage | |
|---|---|---|
| Boilerplate per entity | 1 POJO + 1 handler | Controller + service + repository + DTO + mapper |
| SQL generation | Automatic from annotations | You write it (JPQL, native SQL, or Criteria API) |
| Pagination / sort / filter | Built in — _limit, _offset, _orderBy, per-field filters |
Hand-rolled or Spring Data Pageable (no field-projection negotiation) |
| Export | CsvHandler / ExcelHandler — one interface |
Custom streaming controller |
| Total control | Lifecycle hooks give you extension points; framework owns the plumbing | You own everything — no framework opinions to work around |
| Learning curve | Framework vocabulary (annotations, handlers, stores) | Standard Spring — no extra concepts |
| Debugging | One more layer between your code and the database | Your code IS the layer — stack traces are shorter |
Pick Palmyra when the entity count is high and CRUD is the dominant pattern. Pick plain Spring when every endpoint is bespoke, or you need full control of the SQL and response shape.
vs JOOQ / MyBatis#
Type-safe SQL builders or SQL-template engines — backend only, no framework.
| Palmyra advantage | JOOQ / MyBatis advantage | |
|---|---|---|
| Scope | Full vertical: model → handler → URL → React grid | SQL layer only — you still write controllers, DTOs, and the frontend |
| Speed of delivery | One POJO + one handler = working endpoint | Write exactly the SQL you want — maximum control |
| Client-driven queries | Built in | You build the filter/sort/page logic yourself |
| Complex SQL | NativeQueryHandler for hand-written queries when annotations aren’t enough |
Every query is hand-written — JOOQ adds type safety, MyBatis adds XML mapping |
| Compile-time safety | Runtime annotation processing | JOOQ: compile-time type-checked SQL; MyBatis: IDE-assisted XML |
Pick Palmyra when you want the full stack, not just the SQL layer. Pick JOOQ / MyBatis when your SQL is complex enough that a framework-generated query won’t cut it, and you’re happy to build the REST + frontend layers yourself.
Frontend comparisons#
vs React Admin / Refine#
Data-provider + resource-component frameworks for admin UIs.
| Palmyra advantage | React Admin / Refine advantage | |
|---|---|---|
| Backend match | PalmyraStoreFactory speaks the Palmyra API natively — zero adapter code; custom StoreFactory implementations connect to any backend |
Generic data providers for REST, GraphQL, Supabase, Hasura, Appwrite, … — large catalogue of ready-made adapters |
| Form ↔ store lifecycle | PalmyraNewForm / PalmyraEditForm handle fetch + save + validation in one component |
Richer ecosystem of pre-built “resource” pages and admin chrome |
| UI library | Mantine or MUI — real component-library code, not wrapped | React Admin: MUI only; Refine: headless + optional Ant/MUI/Mantine |
| Plugin ecosystem | Smaller — FilterForm, SelectablePagination, SummaryGrid |
Larger — auth providers, i18n, audit log, realtime, access control built in |
| Community | Emerging | React Admin: 24 k+ GitHub stars; Refine: 29 k+ |
| Backend flexibility | Interface-driven: implement StoreFactory to talk to any backend (REST, GraphQL, Firebase, SOAP) — guide |
Provider-driven: pick a ready-made data provider or write a custom one |
Pick Palmyra’s frontend when you want tight form/grid/store integration and are comfortable implementing a StoreFactory for your backend (zero effort if the backend is Palmyra).
Pick React Admin / Refine when you need a ready-made data-provider catalogue for diverse backends, a broader plugin ecosystem, or community size matters for hiring.
vs React Hook Form + axios + a grid library#
The “assemble it yourself” approach.
| Palmyra advantage | DIY advantage | |
|---|---|---|
| Integration | One factory, one form component, one grid component — wired together; works against any backend via custom StoreFactory |
Mix any grid (AG-Grid, TanStack, MUI DataGrid) with any form (RHF, Formik) and any HTTP client |
| Per-entity boilerplate | 1 endpoint string + attribute props — no per-entity fetch/state code |
Full control — but you write it for every entity |
| Grid features | Paging, sort, search, filter-panel, export — built in | Choose exactly the features you need — nothing forced |
| Escape hatch | useServerQuery and generateColumns give you TanStack Table underneath |
You already have TanStack Table — no abstraction to escape from |
| Bundle size | Palmyra wire + rt-forms + skin | Only the pieces you pick — potentially lighter |
| Learning curve | Framework vocabulary (stores, forms, grids, templates) | Standard React — no extra concepts |
Pick Palmyra when entity count is high and you want to stop writing the same fetch/grid/form wiring for each one. Pick DIY when you have a handful of bespoke screens, bundle size is critical, or you need a grid library Palmyra doesn’t wrap.
vs Retool / Appsmith (low-code)#
Drag-and-drop internal-tool builders.
| Palmyra advantage | Low-code advantage | |
|---|---|---|
| Code ownership | You own every file — version control, code review, CI/CD | Visual builder — non-developers can build screens |
| Customisation | Arbitrary React — any layout, any logic, any library | Constrained to the builder’s widget set and scripting model |
| Deployment | Standard web app — deploy anywhere | Hosted SaaS or self-hosted container |
| Cost at scale | Open source — no per-seat licensing | Per-seat pricing can climb fast with large teams |
| Speed for simple screens | Write code (fast, but still code) | Drag, drop, connect — faster for simple CRUD with no custom logic |
| Complex business logic | Java handler hooks — full language | JavaScript snippets in a sandbox — limited |
Pick Palmyra when the team has developers, the logic is non-trivial, and you need full code ownership. Pick low-code when the screens are simple, the team includes non-developers, and speed to first screen matters more than long-term flexibility.
Full-stack framework comparisons#
vs Ruby on Rails / Django / Laravel#
Server-rendered full-stack frameworks with mature ecosystems.
| Palmyra advantage | Rails / Django / Laravel advantage | |
|---|---|---|
| Architecture | API-first (JSON REST) + separate React SPA — modern client/server split | Monolith with server-rendered HTML — simpler deployment, no CORS, no SPA build step |
| Frontend richness | Full React SPA with Mantine / MUI — richer interactivity | Turbo / HTMX / Livewire add interactivity without a full SPA |
| Performance | Raw JDBC, JVM — strong throughput under load | Interpreted (Ruby/Python/PHP) — typically slower per-request, but fine for most workloads |
| Language | Java (backend) + TypeScript (frontend) — two languages | One language (Ruby / Python / PHP) for both — lower cognitive overhead |
| ORM | Optional — Palmyra generates SQL from annotations; JPA available alongside | ActiveRecord / Django ORM / Eloquent — deeply integrated, heavily documented |
| Ecosystem maturity | Newer; smaller community | Decades of libraries, gems, packages, tutorials, Stack Overflow answers |
| Admin scaffolding | Handler + POJO = endpoint; frontend is explicit code | rails generate scaffold / Django Admin / Nova — instant admin with less code |
Pick Palmyra when you want a Java/React stack, API-first architecture, and client-driven queries. Pick Rails / Django / Laravel when you prefer a monolith, server-rendered HTML, one-language simplicity, or need the depth of a 15+ year ecosystem.
Summary — Palmyra’s sweet spot#
Palmyra is strongest when:
- The problem is entity-heavy CRUD with relational data — many tables, many screens, same patterns.
- The team wants Java on the server and React on the client — and wants them to share a contract, not a build system.
- Client-driven query flexibility matters — the browser decides what it needs, the server compiles it.
- Speed of delivery per entity matters more than maximum control per endpoint.
- The database schema is the source of truth — not an ORM, not a GraphQL schema, not a code generator.
The frontend is also strong when:
- You have a non-Palmyra backend but want Palmyra’s form/grid/store integration — implement a custom
StoreFactoryand every React component works unchanged. - You’re migrating incrementally — start with Palmyra’s React layer against your existing API, then adopt the backend SDK entity by entity.
The advanced pattern library is also a differentiator — production concerns that require bespoke code in most frameworks are documented recipes in Palmyra: approval workflows, child-entity handlers with nested URLs, email outbox, row-level security, dynamic dashboard queries, custom controllers with ACL, filterable dashboards, i18n, discussion threads, and production error handling.
It’s weakest when the API is heavily GraphQL-shaped, the database is NoSQL, the team doesn’t write code (low-code is better), or every endpoint is bespoke enough that a framework adds more concepts than it removes.
Where to start#
- Overview — framework positioning and capabilities.
- Use Cases — business problems and technical problems Palmyra solves.
- My First Application — build a CRUD app end-to-end to feel the difference.
- API Format — the full HTTP contract for mobile / third-party integrators.
- Tutorial — Advanced — 20+ recipes beyond basic CRUD.