Components
Convex Components package up code and data in a sandbox that allows you to confidently and quickly add new features to your backend.
Convex Components are like mini self-contained Convex backends, and installing them is always safe. They can't read your app's tables or call your app's functions unless you pass them in explicitly.
You can read about the full vision in Convex: The Software-Defined Database
The Convex team has built a few components that add new features to your backend. You'll eventually be able to author your own components to use within your project and to share with the community, but we haven't stabilized and documented the authoring APIs yet.
We've listed components built by the Convex team below. Each component is installed as its own independent library from NPM. Check out the component's README for installation and usage instructions. You can see the full directory on the Convex website.
The underlying authoring APIs for components are still in flux. The Convex team authored components listed below will be kept up to date as the APIs change.
Database
Sharded Counter
High throughput counter
Migrations
Manage live site migrations
Aggregate
Efficient sums, counts, randomization and more
Geospatial (Beta)
Efficiently store and query points on the Earth's surface
Durable Functions
Runtime Crons
Register crons programmatically
Workflow (Beta)
Simplify long running code flows
Action Retrier
Retry idempotent external calls
Backend
Integrations
Twilio SMS
Send SMS and query status
Expo Push Notifications
Manage mobile push notifications
LaunchDarkly feature flags
Sync flags from LaunchDarkly
Understanding Components
Components can be thought of as a combination of concepts from frontend components, third party APIs, and both monolith and service-oriented architectures.
Data
Similar to frontend components, Convex Components encapsulate state and behavior and allow exposing a clean interface. However, instead of just storing state in memory, these can have internal state machines that can persist between user sessions, span users, and change in response to external inputs, such as webhooks. Components can store data in a few ways:
- Database tables with their own schema validation definitions. Since Convex is realtime by default, data reads are automatically reactive, and writes commit transactionally.
- File storage, independent of the main app’s file storage.
- Durable functions via the built-in function scheduler. Components can reliably schedule functions to run in the future and pass along state.
Typically, libraries require configuring a third party service to add stateful off-the-shelf functionality, which lack the transactional guarantees that come from storing state in the same database.
Isolation
Similar to regular npm libraries, Convex Components include functions, type safety, and are called from your code. However, they also provide extra guarantees.
- Similar to a third-party API, components can’t read data for which you don’t provide access. This includes database tables, file storage, environment variables, scheduled functions, etc.
- Similar to service-oriented architecture, functions in components are run in an isolated environment, so they can’t read or write global variables or patch system behavior.
- Similar to a monolith architecture, data changes commit transactionally across calls to components, without having to reason about complicated distributed commit protocols or data inconsistencies. You’ll never have a component commit data but have the calling code roll back.
- In addition, each mutation call to a component is a sub-mutation isolated from other calls, allowing you to safely catch errors thrown by components. It also allows component authors to easily reason about state changes without races, and trust that a thrown exception will always roll back the Component’s sub-mutation. Read more.
Encapsulation
Being able to reason about your code is essential to scaling a codebase. Components allow you to reason about API boundaries and abstractions.
- The transactional guarantees discussed above allows authors and users of components to reason locally about data changes.
- Components expose an explicit API, not direct database table access. Data invariants can be enforced in code, within the abstraction boundary. For example, the aggregate component can internally denormalize data, the rate limiter component can shard its data, and the push notification component can internally batch API requests, while maintaining simple interfaces.
- Runtime validation ensures all data that cross a component boundary are validated: both arguments and return values. As with normal Convex functions, the validators also specify the TypeScript types, providing end-to-end typing with runtime guarantees.