Convex 0.18.0 has been released! This release brings security fixes, feature deprecations and other improvements as we’re gearing up for the 1.0 release.


The main updates in 0.18.0 are:

  • Server logs, error messages and stack traces are redacted on prod deployments
  • Internal and public function API is split into api and internal objects
  • Using Maps and Sets is deprecated in database and in function input/output
  • Validator naming changes: v.float64 is replacing v.number and v.int64 is replacing v.bigint

Server logs and errors redacted in production

After you npx convex deploy using 0.18.0 any errors thrown inside of your functions on a production deployment will only report a generic Server error message to the browser console and they will not include a stack trace. console.logs, console.errors etc. called inside of your functions will not be sent to the client from production deployments at all.

This is to prevent secrets leaking from your backend to the client. You can still see logs and full error messages and stack traces on the production deployment’s dashboard.

Dev deployments continue showing logs and errors as before.

Added internal api object

For added clarity we split up the generated api object into two objects: api continues including all your public functions and internal can be used to refer to all your internal functions.

In the following example the internal imported from "../_generated/api" object replaced the api object:

import { action } from "../_generated/server";
import { internal } from "../_generated/api";

export default action(async ({ runMutation }, { planId }) => {
  await runMutation(internal.plans.markPlanAsProfessional, { planId });
  ...
});

Internal functions should be used for all logic that doesn’t need to be exposed to the client. Read more in the docs.

Deprecated Maps and Sets

Maps and Sets were supported in the database and as arguments and return values of functions to mirror the data structures available in JavaScript. In practice they are rarely used, and they do not interface well with non-JS clients and exports to other databases. To avoid unnecessary complexity in the Convex type system and serialization protocol we are deprecating this support in this version of Convex (0.18.0).

In the next version of Convex it will no longer be possible to write Maps and Sets to the database, to pass them as arguments to functions nor to return them from functions. Existing code running on version 0.18.0 or earlier will continue to work with Maps and Sets.

For migrating away from Maps and Sets we suggest:

  1. Instead of Sets use Arrays and the v.array(...) validator
  2. Instead of a Map use

  a. If the keys are strings or IDs: Objects with and the v.any() validator

  b. Otherwise: Arrays of Objects and the v.array(v.object({key: ..., value: ...})) validator

We plan to expand our type system in the near future to include a v.record() validator for typing Objects similarly to Maps with a key and value type. Please reach out if migrating off of Maps will pose a challenge to your project.

Introducing v.float64 and v.int64

The Convex number types stored in the Convex database and the values that can be used as arguments to and returned from functions have always been a 64 bit floating point value and 64 bit integer value. The validators for these types have previously been called based on the JavaScript runtime types used to work with them (v.number and v.bigint). This was confusing because Convex does not actually support BigInts.

Starting with 0.18.0 we are deprecating the v.bigint validator and replacing it with the v.int64 validator, which works exactly the same way at runtime, but better describes which values are allowed (up to 64 bit integers stored in a BigInt).

We have also added the v.float64  validator which is now the preferred default in schemas and input validation. It works exactly the same way as the v.number validator, which can still be used, and will be more familiar to JavaScript and TypeScript developers.