typescriptnext.jsredisvercelserverless

Redis operations on Vercel hang after execution when using Upstash


This code runs without any issues locally, but it hangs when deployed on Vercel. When I check the Redis monitoring in Upstash, I notice that sometimes the data is successfully inserted, while other times it's not. The logs on Vercel show that sometimes the code passes through the await statement, but other times it gets stuck at the await.

I'm using Upstash's Redis with a Pay as You Go plan, and Vercel with Pro plan.

I'm also using Upstash's QStash, and I'm experiencing similar issues. Sometimes it triggers successfully, while other times it gets stuck at the first call. All of these operations work normally when run locally.

import { Redis } from '@upstash/redis'
const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
  enableAutoPipelining: true,
  retry: {
    retries: 5,
    backoff: (retryCount) => Math.exp(retryCount) * 50,
  },
})
const result = await Promise.all([
  redis.hset(taskId + '_info', {platform,searchId,collectionId,}),
  redis.rpush(taskId, ...keywords),
  redis.expire(taskId, TASK_EXPIRY_TIME),
  redis.expire(taskId + '_info', TASK_EXPIRY_TIME)
  ]);```
      

I've attempted several solutions to resolve this issue:

const pipeline = redis.pipeline();
pipeline.hset(taskId + '_info', { /* data */ });
pipeline.rpush(taskId, ...keywords);
pipeline.expire(taskId, TASK_EXPIRY_TIME);
pipeline.expire(taskId + '_info', TASK_EXPIRY_TIME);
const results = await pipeline.exec();

However, this approach still resulted in the same hanging behavior in some cases.


Solution

  • when the auto pipelining is enabled, the code samples you provided are practically equivalent.

    here are two things you can try:

    1. Disable auto pipelining and try running the commands one by one:
    const hsetResult = await redis.hset(taskId + '_info', {platform,searchId,collectionId,})
    const rpushResult = await redis.rpush(taskId, ...keywords)
    const expireResult = await redis.expire(taskId, TASK_EXPIRY_TIME)
    const expireResult2 = await redis.expire(taskId + '_info', TASK_EXPIRY_TIME)
    

    This code is far from ideal as it will result in several requests but can help you debug the error.

    1. Disable retry. If the issue persists, it could be because the sdk is getting an error and appear to be hanging while it's retrying. You could try disabling the retry and check if there is an error.
    const redis = new Redis({
      url: process.env.UPSTASH_REDIS_REST_URL!,
      token: process.env.UPSTASH_REDIS_REST_TOKEN!,
      enableAutoPipelining: true,
      retry: false
    })