Storing data about a user
How the metadata updates work#
In the SuperTokens core, we update the metadata using the following steps:
- Load old metadata from DB or use an empty object if we have nothing stored.
 - Overwrite all root-level properties with the fields of the update object.
 - Remove all root-level properties with a 
nullvalue. 
This way, you can update parts of the metadata object without loading and merging the whole thing yourself.
important
Only root-level properties are merged into the stored object. Nested objects and all lower-level properties will be replaced.
Example#
- The stored object has a theme set in preferences, emails enabled in notifications, and a single todo item, telling them to switch to text messages:
 
{  "preferences": { "theme": "dark" },  "notifications": { "email": true },  "todos": ["use-text-notifs"]}- Now, we want to update this by changing the notification setting and removing the entire todo list:
 
{  "notifications": { "sms": true },  "todos": null}- The result will be then:
 
{  "preferences": { "theme": "dark" },  "notifications": { "sms": true }}How to use#
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - AWS Lambda / Netlify
 - Next.js
 - NestJS
 
import express from "express";import { verifySession } from "supertokens-node/recipe/session/framework/express";import UserMetadata from "supertokens-node/recipe/usermetadata";
let app = express();
app.post("/updateinfo", verifySession(), async (req, res) => {  const session = req.session;  const userId = session.getUserId();
  await UserMetadata.updateUserMetadata(userId, { newKey: "data" });
  res.json({ message: "successfully updated user metadata" });});import Hapi from "@hapi/hapi";import { verifySession } from "supertokens-node/recipe/session/framework/hapi";import { SessionRequest } from "supertokens-node/framework/hapi";import UserMetadata from "supertokens-node/recipe/usermetadata";
let server = Hapi.server({ port: 8000 });
server.route({  path: "/updateinfo",  method: "post",  options: {    pre: [      {        method: verifySession(),      },    ],  },  handler: async (req: SessionRequest, res) => {    const session = req.session;    const userId = session!.getUserId();
    await UserMetadata.updateUserMetadata(userId, { newKey: "data" });    return res.response({ message: "successfully updated user metadata" }).code(200);  },});import Fastify from "fastify";import { verifySession } from "supertokens-node/recipe/session/framework/fastify";import UserMetadata from "supertokens-node/recipe/usermetadata";
let fastify = Fastify();
fastify.post(  "/updateinfo",  {    preHandler: verifySession(),  },  async (req, res) => {    const session = req.session;    const userId = session.getUserId();
    await UserMetadata.updateUserMetadata(userId, { newKey: "data" });    res.send({ message: "successfully updated user metadata" });  },);import { verifySession } from "supertokens-node/recipe/session/framework/awsLambda";import { SessionEvent } from "supertokens-node/framework/awsLambda";import UserMetadata from "supertokens-node/recipe/usermetadata";
async function updateinfo(awsEvent: SessionEvent) {  const session = awsEvent.session;  const userId = session!.getUserId();
  await UserMetadata.updateUserMetadata(userId, { newKey: "data" });
  return {    body: JSON.stringify({ message: "successfully updated user metadata" }),    statusCode: 200,  };}
exports.handler = verifySession(updateinfo);import KoaRouter from "koa-router";import { verifySession } from "supertokens-node/recipe/session/framework/koa";import { SessionContext } from "supertokens-node/framework/koa";import UserMetadata from "supertokens-node/recipe/usermetadata";
let router = new KoaRouter();
router.post("/updateinfo", verifySession(), async (ctx: SessionContext, next) => {  const session = ctx.session;  const userId = session!.getUserId();
  await UserMetadata.updateUserMetadata(userId, { newKey: "data" });  ctx.body = { message: "successfully updated user metadata" };});import { inject, intercept } from "@loopback/core";import { RestBindings, post, response } from "@loopback/rest";import { verifySession } from "supertokens-node/recipe/session/framework/loopback";import { SessionContext } from "supertokens-node/framework/loopback";import UserMetadata from "supertokens-node/recipe/usermetadata";
class UpdateInfo {  constructor(@inject(RestBindings.Http.CONTEXT) private ctx: SessionContext) {}  @post("/updateinfo")  @intercept(verifySession())  @response(200)  async handler() {    const session = this.ctx.session;    const userId = session!.getUserId();
    await UserMetadata.updateUserMetadata(userId, { newKey: "data" });    return { message: "successfully updated user metadata" };  }}import { superTokensNextWrapper } from "supertokens-node/nextjs";import { verifySession } from "supertokens-node/recipe/session/framework/express";import { SessionRequest } from "supertokens-node/framework/express";import UserMetadata from "supertokens-node/recipe/usermetadata";
export default async function updateInfo(req: any, res: any) {  await superTokensNextWrapper(    async (next) => {      await verifySession()(req, res, next);    },    req,    res,  );  const session = (req as SessionRequest).session;  const userId = session!.getUserId();
  await UserMetadata.updateUserMetadata(userId, { newKey: "data" });  res.json({ message: "successfully updated user metadata" });}import { Controller, Post, UseGuards, Session } from "@nestjs/common";import { SessionContainer } from "supertokens-node/recipe/session";import UserMetadata from "supertokens-node/recipe/usermetadata";import { AuthGuard } from "./auth/auth.guard";
@Controller()export class ExampleController {  // For more information about "AuthGuard" and the "Session" decorator please read our NestJS guide.  @Post("example")  @UseGuards(new AuthGuard())  async postExample(@Session() session: SessionContainer): Promise<{ message: string }> {    const userId = session.getUserId();
    await UserMetadata.updateUserMetadata(userId, { newKey: "data" });    return { message: "successfully updated user metadata" };  }}import "github.com/supertokens/supertokens-golang/recipe/usermetadata"
func main() {    userId := "..."
    usermetadata.UpdateUserMetadata(userId, map[string]interface{}{        "newKey": "data",    })}- Asyncio
 - Syncio
 
from supertokens_python.recipe.usermetadata.asyncio import update_user_metadata
async def some_func():    user_id = "..."
    await update_user_metadata(user_id, {        "newKey": "data"    })from supertokens_python.recipe.usermetadata.syncio import update_user_metadata
user_id = "..."
update_user_metadata(user_id, {    "newKey": "data"})