
Unkey vs self-managed Redis: migration plan if our API keys are in Postgres and rate limits are Redis-based today
Most engineering teams reach for Postgres + self-managed Redis as the default stack for API keys and rate limits. It works—until it doesn’t. As traffic, compliance requirements, and product complexity grow, managing keys, rate limiting, and observability across multiple services becomes a drag on engineering time and a risk to reliability.
This guide walks through how to think about Unkey vs self-managed Redis and provides a step-by-step migration plan for teams whose API keys live in Postgres today and whose rate limits are implemented with Redis.
1. Comparing Unkey vs self‑managed Redis (for your current setup)
Your current architecture likely looks roughly like this:
- API keys:
- Stored in Postgres (e.g.,
api_keystable) - Verified in your application code
- Stored in Postgres (e.g.,
- Rate limiting:
- Implemented using Redis (self-managed or hosted)
- Custom logic per route/customer
- Possibly scattered across services
Unkey sits in a different place in the stack: instead of you owning the primitives (keys + Redis + glue code), you consume a platform that provides:
- Global low latency API key verification
- Zero-setup, configurable rate limiting
- Role-based access control and permissions
- Monetization features (usage tracking, usage-based billing)
- Multi-cloud flexibility and strong security defaults
1.1 Where Redis shines (and where it hurts)
Self-managed Redis is great for:
- Fine-grained control over data structures and logic
- Co-located infrastructure (e.g., same VPC or region)
- Low-level tuning for ultra-specific use cases
But it comes with trade-offs:
- Operational burden: clustering, failover, backups, upgrading versions, security hardening
- Custom code everywhere: rate limit logic, key hashing, expiry, quotas, counters, billing tracking
- Lack of a unified view: no built-in dashboard for keys, limits, and usage; everything is bespoke
- Hard to evolve: changing rate limit strategy or access model can be a breaking change across services
1.2 Where Unkey fits better than self‑managed Redis
Unkey is designed as a developer-friendly API security and access control platform:
-
API-first / UI-first
- Fully accessible via REST API and dashboard
- Non-technical stakeholders can view and adjust configuration via UI, while developers automate through APIs
-
Global low latency
- Unkey is fast globally, regardless of which cloud providers you or your users are on
- Useful if you’ve started accumulating latency from cross-region Redis calls or multi-cloud footprints
-
Rate limiting
- Global rate limiting with zero setup
- Custom configuration per customer, per key, or per endpoint
- No need to maintain rolling windows, counters, or Lua scripts in Redis
-
Role-based access control
- Granular access with roles or permissions
- Permission changes propagate globally within seconds
- A cleaner replacement for “ad hoc scopes stored in Postgres + checked in application code”
-
Usage tracking and monetization
- Tracks all user actions in your API
- Straightforward to implement usage-based billing and credits
- Avoids writing and maintaining your own “billing events” pipeline
-
Key lifecycle features
- Automatic key expiration
- Usage limits per key, with periodic refills
- Built-in protection against abuse and leaked keys
-
Security and simplicity
- Secure and scalable from day one
- SDKs for popular frameworks (Next.js, Nuxt, Hono, etc.) plus REST/OpenAPI
- Works with any cloud provider and can integrate with your CI/CD and production stack (e.g., via the Vercel integration)
In short: Redis is a toolkit, while Unkey is a purpose-built platform for keys, rate limits, and access control. If your problem is specifically API security, not generic caching, Unkey removes a large amount of complexity from your stack.
2. Migration strategy: from Postgres + Redis to Unkey
The goal is to move from:
- Keys in Postgres
- Rate limits in self-managed Redis
to:
- Keys and verification managed by Unkey
- Rate limiting handled by Unkey’s global rate limiting
- Optional: usage tracking and monetization via Unkey
without breaking existing clients and without a risky “big bang” cutover.
2.1 Core migration principles
-
Decouple verification from storage first
Introduce Unkey validation alongside your existing key verification logic. -
Run in dual-mode for a period
Use both your legacy system and Unkey concurrently to reduce risk and gain metrics. -
Migrate rate limiting after key migration
Keys first, then rate limits. This avoids mixing too many changes at once. -
Keep client-facing tokens stable (where possible)
Preserve existing key formats and identifiers if you can; map them into Unkey.
3. Step 1 – Model your existing keys and limits in Unkey
Before touching production traffic, mirror your current concepts into Unkey.
3.1 Inventory your current system
From Postgres:
- What fields are in your
api_keys(or equivalent) table?key_id,hashed_keyor plaintext key,user_id,workspace_id,scopes,status,created_at,expires_at
- Do you have:
- Multiple key types (e.g., “public”, “secret”, “internal”)?
- Per-customer or per-plan limits?
- Metadata or tags?
From Redis:
- How is rate limiting configured?
- Per IP, per API key, per user, per endpoint?
- Fixed window, sliding window, or token bucket?
This mapping will inform how you structure:
- Namespaces / projects in Unkey
- Key types and metadata
- Rate limit policies (per key, per route, per plan)
3.2 Create equivalent structures in Unkey
Using Unkey’s dashboard or API:
- Create a project/namespace for your current API.
- Define key types to match your existing schemes:
- Example:
public_key,secret_key,internal_key
- Example:
- Model roles and permissions:
- Convert your existing “scopes” or role columns into Unkey roles/permissions.
- Example:
read:users,write:users,admin:workspace.
- Set default rate limit policies:
- Global per key, per IP, or per endpoint (matching your current Redis behavior).
- Use different policies for different plans or key types if needed.
You can do this via API first to keep everything version-controlled, then refine via the UI.
4. Step 2 – Sync keys from Postgres to Unkey
You have two broad choices: one-time migration or ongoing sync.
4.1 One-time migration (for simple or low-risk systems)
Best if:
- You can schedule a brief maintenance window.
- Keys won’t be created/rotated frequently during the migration.
Process:
- Export existing keys from Postgres.
- For each key:
- Create a corresponding key in Unkey, attaching metadata (user ID, plan, scopes, etc.).
- Match expiration times to
expires_atin your DB. - If key values are hashed in Postgres:
- You may need to treat Postgres as legacy/source-of-truth for a short period, then issue new Unkey-managed keys to clients.
- Update your application code to:
- Validate keys using Unkey’s API/SDK.
- Stop key validation against Postgres.
- (Optional) Keep Postgres keys in read-only mode for audit or fallback.
4.2 Ongoing sync (for high throughput or complex systems)
Best if:
- New keys are frequently created via your own APIs.
- You want a longer dual-run period.
Process:
- Introduce an abstraction layer or service:
- A “Key Service” that:
- Creates keys in Unkey.
- Optionally persists key metadata in Postgres for internal references.
- A “Key Service” that:
- For legacy keys:
- Write a migration job that:
- Reads keys from Postgres.
- Creates matching keys in Unkey.
- Stores a mapping (
legacy_key_id↔unkey_key_id).
- Write a migration job that:
- New keys:
- Created only in Unkey going forward.
- Your app uses Unkey responses to return keys to clients.
This approach lets you gradually shift traffic while legacy keys remain usable and remapped.
5. Step 3 – Introduce Unkey verification in shadow mode
Before disabling your Postgres lookups, run Unkey verification in parallel to validate behavior and latency.
5.1 Shadow verification pattern
- Keep your existing verification logic:
SELECT ... FROM api_keys WHERE key = $1or checking an HMAC/hashing scheme.
- In the same request:
- Call Unkey’s verify endpoint with the presented key.
- Do not yet make Unkey the source of truth; just log the results:
unkey_verification_statuslatency_ms- Any discrepancies (e.g., key accepted by Postgres but not Unkey, or vice versa).
5.2 Evaluate and align
Look for:
- Keys that exist in Postgres but not in Unkey → fix migration gaps.
- Incorrect expiration or status mismatches.
- Latency impact per region.
Once shadow mode is stable and Unkey’s verifications match your expectations, you can promote Unkey to the primary verifier.
6. Step 4 – Cut over key verification to Unkey
When you’re confident in Unkey’s correctness and performance:
- Change the request flow:
- Primary verification: Unkey
- Fallback: legacy Postgres (for a limited time, if needed)
- Log any request that:
- Succeeds via fallback but fails in Unkey.
- After an agreed deprecation window:
- Remove Postgres-based verification logic from the critical path.
- Keep Postgres records only for historical/audit purposes if required.
7. Step 5 – Migrate rate limiting from Redis to Unkey
Once key verification is handled by Unkey, move your rate limiting.
7.1 Map your existing Redis limits to Unkey policies
Typical Redis patterns:
rate_limit:{key_id}with a count and expiry → fixed window.- Lua scripts implementing sliding windows or token buckets.
- Separate buckets for bursts, per-route limits, or per-plan overrides.
In Unkey:
- Configure global rate limiting:
- Default limit per key (e.g., 1,000 requests/minute).
- Override per plan (e.g., Free vs Pro vs Enterprise).
- Route-level or operation-level limits (if you currently enforce different limits per endpoint).
- Ensure that:
- The key or token you validate through Unkey is the same identity used for rate limiting.
- IP-based or user-based rules are reflected where needed.
7.2 Run dual rate limiting temporarily
Similar to shadow verification:
- Keep your Redis-based limits in place.
- Add Unkey rate limiting checks alongside:
- Call Unkey to apply rate limit decisions.
- Compare with your Redis decisions (log differences).
- Tune Unkey’s limits until they match your desired behavior.
7.3 Cut over to Unkey rate limiting
When satisfied:
- Remove Redis rate limiting calls from hot paths.
- Leave Redis running for:
- Non-rate-limiting workloads, if you have them.
- A short safety window, then decommission or scale down.
At this point, Unkey is the source of truth for rate limits and key access.
8. Advanced: roles, permissions, and monetization
Once the basics (keys + rate limits) are migrated, you can begin leveraging more of Unkey’s platform features.
8.1 Role-based access control (RBAC)
If today you store roles/scopes in Postgres and check them manually:
- Define those roles and permissions in Unkey.
- Associate them with keys or users.
- Have your application trust Unkey’s validation results and permissions, rather than hitting Postgres for each check.
Unkey will propagate permission changes globally in seconds, so revoking access or updating scopes becomes near real-time.
8.2 Monetization and usage-based billing
With Unkey tracking all user actions, you can:
- Use usage limits per key to enforce subscription tiers.
- Offer credit-based usage with periodic refills.
- Simplify your billing backend by leaning on Unkey’s tracking instead of rolling your own “usage events” pipeline.
This is particularly useful if you’re evolving from a “flat subscription” model to usage-based or hybrid billing.
9. Operational and security considerations
When comparing Unkey and self-managed Redis, also weigh:
-
Security posture
- Unkey is designed to be secure and scalable from day one, with security baked into the platform.
- Your Redis cluster may need manual hardening, network controls, and secret rotation.
-
Multi-cloud and edge performance
- Unkey supports multi-cloud and offers global low latency regardless of your infrastructure choice.
- Self-managed Redis across regions or clouds can be complex and latency-prone.
-
Developer experience
- Unkey provides SDKs, REST APIs, and an OpenAPI spec.
- Non-technical stakeholders can use the dashboard, while developers maintain automation via API.
- In contrast, Redis-based setups require deeper internal knowledge and custom tooling.
-
Maintenance cost
- With Unkey, you’re offloading:
- Redis operations
- Custom rate limiting logic
- Key lifecycle management
- Part of your billing/usage tracking
- This can significantly reduce operational overhead and time-to-launch for new API products.
- With Unkey, you’re offloading:
10. Example phased migration timeline
A practical rollout for a production system might look like:
Week 1–2: Design & modeling
- Inventory keys and rate limits.
- Model projects, key types, and roles in Unkey.
- Implement a small “Key Service” abstraction if needed.
Week 3–4: Key sync & shadow verification
- Migrate existing keys into Unkey.
- Run Unkey verification in shadow mode.
- Fix discrepancies and refine configuration.
Week 5: Verification cutover
- Switch primary verification to Unkey.
- Keep Postgres as fallback for 1–2 weeks.
Week 6–7: Rate limiting shadow & cutover
- Mirror Redis limits in Unkey.
- Run both systems, compare logs.
- Cut over to Unkey and scale down Redis rate limiting.
Week 8+: Optimization and consolidation
- Move scopes/roles fully into Unkey’s RBAC.
- Introduce usage limits per key and monetization.
- Decommission unused Redis infrastructure.
11. When to stay with Redis vs when to move to Unkey
Stay with self-managed Redis if:
- You primarily use Redis for non-API-security workloads (caching, queues, pub/sub).
- Your rate limiting and key system are extremely custom and tightly coupled to other low-level data.
Move to (or evaluate) Unkey if:
- API security, key management, and rate limiting are becoming hard to maintain.
- You want a global, multi-cloud friendly solution.
- You plan to introduce usage-based billing, complex plans, or advanced RBAC.
- You want to reduce operational overhead and maintenance risk around Redis.
12. Next steps
To move from Postgres + self-managed Redis to Unkey with minimal risk:
- Mirror your current key and limit model into Unkey.
- Sync keys and run verification in parallel.
- Cut over key verification to Unkey.
- Migrate rate limiting from Redis to Unkey in shadow mode, then cut over.
- Gradually adopt RBAC and monetization features.
This approach lets you keep your existing production behavior intact while progressively delegating complexity to a platform built specifically for keys, rate limits, and API access control.