You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hasura/PostgreSQL数据库中存储临时数据?——针对入职流程验证码的无残留Schema需求

Great question! Storing temporary verification data without cluttering your core schema is a super common need for onboarding flows—let’s break down the best approaches tailored for Hasura and PostgreSQL:

1. Universal Temporary Table with Type Differentiation

This is my go-to solution when I want to avoid schema bloat but still keep everything within PostgreSQL. Instead of creating separate tables for email, SMS, or other verification types, use a single table with a type field to distinguish between them.

Step 1: Create the Table

First, set up a reusable table with all necessary fields, plus an enum to standardize verification types:

-- Create an enum for verification types (extend with 'sms', 'totp', etc. as needed)
CREATE TYPE verification_type AS ENUM ('email');

CREATE TABLE temp_verifications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) ON DELETE CASCADE, -- Link to your user table
    type verification_type NOT NULL,
    code VARCHAR(10) NOT NULL, -- Adjust length based on your code format
    expires_at TIMESTAMPTZ NOT NULL, -- Auto-expire logic
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Add indexes to speed up queries and cleanup
CREATE INDEX idx_temp_verifications_user_type ON temp_verifications(user_id, type);
CREATE INDEX idx_temp_verifications_expires_at ON temp_verifications(expires_at);

Step 2: Configure Hasura Permissions

Keep this table secure by restricting access:

  • Insert: Only allow users to insert records where user_id matches their own session ID.
  • Select: Only let users query their own records where expires_at > NOW() (so expired codes are invisible).
  • Delete: Either let users delete their own records after verification, or automate cleanup.

Step 3: Automate Cleanup

Use PostgreSQL’s pg_cron extension to auto-delete expired data (no manual work needed):

-- Install pg_cron if you haven't already
CREATE EXTENSION IF NOT EXISTS pg_cron;

-- Schedule daily cleanup at 2 AM (adjust timing to your needs)
SELECT cron.schedule('cleanup-temp-verifications', '0 2 * * *', $$
    DELETE FROM temp_verifications WHERE expires_at < NOW();
$$);

Alternatively, use Hasura Event Triggers to delete a record right when it expires—set a delayed trigger on insert that fires at expires_at.

2. Redis + Hasura Actions (No Schema Changes)

If you want to keep PostgreSQL completely untouched, use Redis for temporary storage (it’s built for short-lived data). Pair it with Hasura Actions to handle code generation and verification.

Step 1: Set Up Redis

Spin up a Redis instance (local or managed) and configure TTL (time-to-live) for your verification keys—this automatically deletes codes after expiration.

Step 2: Define Hasura Actions

Create two actions in Hasura:

  1. Generate Verification Code: Takes a user ID and email, generates a code, stores it in Redis with a TTL (e.g., 5 minutes), and returns the code to the frontend.
  2. Verify Code: Takes a user ID and code, checks Redis for the matching key, and returns a boolean for validity.

Example backend logic (Node.js snippet for the generate action):

const redis = require('redis');
const client = redis.createClient({ url: 'redis://your-redis-instance' });
client.connect();

async function generateEmailCode(req) {
  const { userId, email } = req.input;
  const code = Math.floor(100000 + Math.random() * 900000).toString(); // 6-digit code
  
  // Store code with 5-minute TTL
  await client.setEx(`verification:email:${userId}`, 300, code);
  
  return { success: true, code };
}
3. JSONB Field on User Table (Minimal Schema Impact)

If you want to avoid creating a new table entirely, add a JSONB field to your existing users table to store all temporary verification data in one place.

Step 1: Add the JSONB Field

ALTER TABLE users ADD COLUMN temp_verifications JSONB DEFAULT '{}'::JSONB;

Step 2: Store and Verify Codes

Use Hasura mutations to update the JSONB field with verification data:

mutation SaveEmailCode($userId: UUID!, $code: String!, $expiresAt: timestamptz!) {
  update_users_by_pk(
    pk_columns: { id: $userId },
    _set: {
      temp_verifications: {
        "email": {
          "code": $code,
          "expires_at": $expiresAt
        }
      }::jsonb
    }
  ) {
    id
  }
}

Step 3: Clean Up Expired Data

Use pg_cron to remove expired entries from the JSONB field:

SELECT cron.schedule('cleanup-user-verifications', '0 2 * * *', $$
  UPDATE users
  SET temp_verifications = temp_verifications #- '{email}'
  WHERE (temp_verifications->'email'->>'expires_at')::TIMESTAMPTZ < NOW();
$$);
Which Should You Choose?
  • Universal Temporary Table: Best for most cases—clean, scalable, and fully integrated with Hasura’s permissions and events.
  • Redis + Actions: Perfect if you want zero PostgreSQL schema changes or already use Redis for caching.
  • JSONB Field: Good for small-scale apps where you want to minimize table count, though querying and cleanup are slightly more complex.

内容的提问来源于stack exchange,提问作者Sasial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:39:07