Indexes have arrived! Now you can query large datasets efficiently and with confidence!

This changes in this release are:

  • Indexes
  • Bye Bye Beta Keys
  • Simpler Authentication
  • Minor Improvements

As always, if you have any questions about these new features, reach out in our Convex Slack Community!

Indexes

Indexes are a data structure that allow you to speed up your database queries by telling Convex how to organize your documents.

If you are new to database indexes, we highly recommend starting with the Introduction to Indexes and Query Performance.

In Convex, indexes are defined as part of your schema in convex/schema.ts:

import { defineSchema, defineTable, s } from "convex-dev/schema";

export default defineSchema({
  // Define a messages table with an index on (channel, time).
  messages: defineTable({
    channel: s.id(),
    body: s.string(),
    time: s.number(),
    user: s.id(),
  }).index("by_channel_and_time", ["channel", "time"]),
  // ...
});

Once you’ve defined your index, you can use it in your query and mutation functions:

// Find messages in `channel` created 1-2 minutes ago, ordered by `time`.
const messages = await db
  .table("messages")
  .index("by_channel_and_time")
  .range(q =>
    q
      .eq("channel", channel)
      .gt("time", Date.now() - 2 * 60000)
      .lt("time", Date.now() - 60000)
  )
  .collect();

Database queries are always explicit about how they will use the index, so you can have confidence that they will be efficient. The range method defines which documents Convex should consider when running the query. The generated TypeScript types ensure that you’ll use range correctly.

To learn more about indexes, read the documentation!

Bye Bye Beta Keys

Convex beta keys are now a thing of the past! We’re moving to an open beta where developers can use Convex without waiting in line.

To replace beta keys, we have a new npx convex login command. This command will authenticate you via Github and save a token in ~/.convex/config.json. You’ll be prompted to run this command before provisioning or deactivating deployments in the CLI.

Simpler Authentication

This release includes a brand new ConvexProviderWithAuth0 React component. This component simplifies the process of using Auth0 authentication in your Convex app:

import { ConvexReactClient } from "convex-dev/react";
import { ConvexProviderWithAuth0 } from "convex-dev/react-auth0";
import convexConfig from "../convex.json";

const convex = new ConvexReactClient(convexConfig.origin);
const authInfo = convexConfig.authInfo[0];

export default function App() {
  return (
    <ConvexProviderWithAuth0 client={convex} authInfo={authInfo}>
      <AppComponent />
    </ConvexProviderWithAuth0>
  );
}

You can customize your login experience by adding custom logged out and loading states. To learn more, see our updated Authentication Tutorial.

And as before, you can continue to manually handle authentication and call ConvexReactClient.setAuth directly.

Minor Improvements

  • The output of npx convex push --dry-run is more readable and includes index information.
  • Authentication errors, like calling ConvexReactClient.setAuth with an invalid token, now generate readable error messages.
  • useQuery and useMutation now have better editor support. In editors like VSCode, you’ll now see the argument names of your query and mutation functions when you invoke them from React.
  • The data view in the dashboard now has resizable columns and shows the newest documents at the top.
  • We’ve also made lots of other minor improvements to the dashboard.