Skip to content

What is Groveback

Groveback is an open-source Backend-as-a-Service for MongoDB. It gives you the pieces you would otherwise rebuild in every project — end-user authentication, a CRUD API over your collections, file storage, event-driven functions, realtime subscriptions and vector search — behind one server you can run locally or self-host.

If you know Supabase, the developer experience is the target. The implementation is necessarily different, and that difference is worth understanding before anything else.

Supabase can let a browser talk almost directly to the database because Postgres has row-level security: a policy is declared in SQL and the engine enforces it row by row.

MongoDB has no equivalent. Its native RBAC is collection-grained, views are static, and $redact cannot express dynamic per-tenant rules. So Groveback makes the opposite choice:

Groveback is the permission authority, enforced in the application layer. The client never talks to MongoDB directly.

The data API is a mandatory choke point, not a convenience. There is no “direct” mode to opt into, and every path that reads documents — REST, GraphQL, realtime, the function runtime’s ctx.db — goes through the same policy engine.

Two consequences you will feel while building:

  • The data plane is fail-closed. A collection with no policy denies every non-admin caller. You do not accidentally ship an open collection.
  • Policies are query fragments, not filters applied in code. They are injected into the Mongo query with $and, so the database enforces them, your indexes still apply, and pagination stays correct. See authorization policies.

Auth — email/password with sessions, refresh-token rotation, email verification, password recovery and rate limiting, plus Google and GitHub social login configured per project. See end-user auth.

Data API — per-collection REST CRUD with optional JSON-Schema validation, relations, and a query syntax for filtering, sorting, projecting and paginating. See collections.

GraphQL — a per-project schema at POST /api/v1/graphql, either generic or typed from your collection schemas. Resolvers call the same document service as REST, so policies apply identically.

Realtime — WebSocket subscriptions over MongoDB Change Streams, with the read policy re-applied to every event before it is emitted.

Functions — sandboxed handlers that run on database, auth and storage events, or serve custom HTTP endpoints. pre hooks run synchronously before a write and can abort or mutate it; post hooks run after. The sandbox has no database client and no secrets — functions reach data only through a host-mediated ctx.db bridge.

Storage — buckets over any S3-compatible object store, falling back to MongoDB when no S3 is configured.

Vector search — embeddings and similarity queries, for retrieval-augmented apps.

Admin surfaces — a Supabase-style dashboard, an OpenAPI 3.1 document at /api/v1/openapi.json, GraphiQL, an MCP server so an AI client can build your backend by conversation, and the grove CLI.

This trips people up early, so it is worth stating plainly. Groveback distinguishes:

Population Entity Who they are
Platform users membership + platform account Developers who use the dashboard and manage projects
End users User in the project database People who sign into the app you built

They live in separate namespaces with separate role registries. A member role governs what you can do to a project; an end-user role governs what an app’s user can do to documents. Neither can be used in place of the other.

This is also why users is a reserved collection name: Groveback already gives you end-user auth at /api/v1/auth/*. For extra per-user fields, keep your own collection keyed by the uid.

The intended loop is local-first and file-based:

  1. grove dev starts a real backend on your machine — no database, no account.
  2. You design collections in the dashboard wizard or by writing JSON files.
  3. grove pull mirrors the project’s shape into a groveback/ bundle you commit, so schema changes show up as a reviewable diff in a pull request.
  4. grove gen generates a typed client from the live schema.
  5. grove push applies the bundle to a deployed project — after a plan you confirm.

Shape travels both ways. Data never travels between projects: a config export is shape-only by design, so there is no path that pulls documents out of production or writes them into it. Local data comes from fixtures you commit.

Start with the quickstart, or read the core concepts first if you would rather see the whole vocabulary before typing anything.