Skip to main content
RapidDev - Software Development Agency
bubble-integrationsBubble API Connector

Redis

Connect Bubble to Redis using Upstash's HTTP REST API and the Bubble API Connector. Upstash exposes every Redis command as a plain HTTPS GET request, so your Bubble workflows can cache expensive API responses, run rate-limit counters, and store session flags — all without opening a TCP socket. Your Upstash REST token stays server-side in a Private header and never reaches the browser.

What you'll learn

  • Why Upstash is the correct Redis provider for Bubble (HTTP REST vs TCP)
  • How to set up the Bubble API Connector with a Private Bearer token for Upstash
  • How to create GetKey, SetKey, and IncrKey API Connector calls
  • How to build a cache-check workflow that skips expensive API calls when a cached value exists
  • How to implement per-user rate limiting using INCR and EXPIRE commands
  • How to avoid Workload Unit (WU) waste through smart cache-first patterns
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read45 minutesDatabase & BackendLast updated July 2026RapidDev Engineering Team
TL;DR

Connect Bubble to Redis using Upstash's HTTP REST API and the Bubble API Connector. Upstash exposes every Redis command as a plain HTTPS GET request, so your Bubble workflows can cache expensive API responses, run rate-limit counters, and store session flags — all without opening a TCP socket. Your Upstash REST token stays server-side in a Private header and never reaches the browser.

Quick facts about this guide
FactValue
ToolRedis
CategoryDatabase & Backend
MethodBubble API Connector
DifficultyIntermediate
Time required45 minutes
Last updatedJuly 2026

Why Upstash is the Redis bridge Bubble actually needs

Classic Redis clients use a binary protocol over TCP port 6379 with a persistent connection — none of which Bubble's workflow runtime supports. Upstash solves this by exposing every Redis command as a plain HTTPS URL path: `/get/{key}` returns the stored value, `/set/{key}/{value}?ex=3600` stores it with a TTL, `/incr/{key}` increments a counter and returns the new value. Bubble's API Connector treats Upstash exactly like any other REST API.

The primary Bubble use cases for Redis are: (1) caching slow third-party API responses — store a JSON blob with a TTL so repeated Bubble page loads skip the expensive external call; (2) per-user rate-limit counters — INCR a key on each user action, check the count, and block if the threshold is exceeded; (3) session flags — store a simple boolean or token string that drives Bubble conditions without a database round-trip.

Upstash's free tier covers 10,000 commands per day. For most Bubble apps, this is sufficient during development. Production traffic should move to the pay-as-you-go plan priced per 100,000 commands — check current rates at upstash.com/pricing. Note that Bubble's API Workflows (needed for scheduled cache-warming or server-triggered cache invalidation) require a paid Bubble plan and are not available on the Free tier.

Integration method

Bubble API Connector

Call Upstash Redis REST API from Bubble's server-side API Connector using a Bearer token in a Private header.

Prerequisites

  • A Bubble app on any plan (Free plan works for basic API Connector usage; paid plan required for API Workflows / scheduled cache warming)
  • An Upstash account at console.upstash.com (free tier available)
  • The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble → Install)

Step-by-step guide

1

Create an Upstash Redis database and copy your credentials

Go to console.upstash.com and sign in or create a free account. Click 'Create Database' and choose a name and region closest to your users. Select the 'Global' option if your Bubble app serves users in multiple regions. Once the database is created, you land on its detail page. You need two values: the REST URL (it looks like `https://global-loved-hedgehog.upstash.io` — unique to your database) and the REST Token (a long string starting with `A...`). Copy both into a temporary text file. Keep the REST Token private — it has full read and write access to your database, including destructive commands like FLUSHALL. The Upstash free tier allows 10,000 commands per day, resetting at midnight UTC. If your Bubble app runs high traffic, monitor usage in the Upstash console and upgrade to pay-as-you-go before hitting the daily limit.

Pro tip: Under 'REST API' on your Upstash database page, Upstash shows ready-to-use curl examples for common commands. Test a SET and GET command from your browser's address bar to confirm the REST URL and token work before configuring Bubble.

Expected result: You have the Upstash REST URL and REST Token copied and ready. You can optionally test a GET request in your browser: open `https://{your-db-id}.upstash.io/get/testkey` — you should see `{"result":null}` since the key does not exist yet.

2

Add Upstash as an API Connector in Bubble with a Private Bearer token

In your Bubble editor, click the Plugins tab in the left sidebar. If 'API Connector' by Bubble is not already listed, click 'Add plugins', search for 'API Connector', and install it. Now click 'API Connector' in your plugins list and then 'Add another API'. Name it 'Upstash Redis'. In the 'Root URL' field, paste your Upstash REST URL: `https://{your-db-id}.upstash.io`. Below the root URL, you see 'Shared headers'. Click 'Add a shared header'. In the Key field type `Authorization`, in the Value field type `Bearer ` followed by your Upstash REST Token (leave a space after 'Bearer'). Most importantly: check the checkbox labeled 'Private'. The Private checkbox tells Bubble to process this header on its servers and never include the raw token value in any client-side code or browser network requests. This is the correct and only safe place for the Upstash REST Token.

upstash-api-connector-config.json
1{
2 "root_url": "https://{your-db-id}.upstash.io",
3 "shared_headers": [
4 {
5 "key": "Authorization",
6 "value": "Bearer <your-upstash-rest-token>",
7 "private": true
8 }
9 ]
10}

Pro tip: Upstash also issues a read-only REST token if you want to restrict certain Bubble calls to read access only. Consider using read-only tokens for GetKey calls that run on page load, and keep the full read-write token only for write operations.

Expected result: The Upstash Redis API group appears in your API Connector plugin with the root URL set and the Authorization header marked Private. No individual calls have been added yet.

3

Create the GetKey call and initialize it with a test key

Inside the Upstash Redis API group, click 'Add another call'. Name this call 'GetKey'. Set the method to GET (Upstash REST uses GET for all commands, including reads and writes — this is intentional and correct). In the endpoint field, type `/get/{{key}}`. The `{{key}}` placeholder becomes a dynamic parameter you pass from Bubble workflows. Click the small wrench icon next to `key` to mark it as a 'Path' parameter and give it a default test value like `test_key`. Now click 'Initialize the call'. Bubble needs to make a real, successful HTTP request to detect the response shape. The call will return {"result":null} because `test_key` does not exist in your database — that is a valid response. Click 'Save' on the response shape. Set 'Use as' to 'Data' so Bubble creates a data type from the response. The detected type will have a single field: `result` (text). This is the field you read in subsequent workflow conditions.

upstash-getkey-call.json
1{
2 "method": "GET",
3 "endpoint": "/get/{{key}}",
4 "params": [
5 {
6 "key": "key",
7 "value": "test_key",
8 "type": "path",
9 "private": false
10 }
11 ]
12}

Pro tip: If 'Initialize the call' returns an error like 'There was an issue setting up your call', double-check that your Authorization header is spelled exactly as `Authorization: Bearer <token>` with a space between 'Bearer' and your token, and that the root URL does not have a trailing slash.

Expected result: The GetKey call initializes successfully and Bubble detects a response with a `result` field. The data type 'GetKey' is now available in your Bubble app for use in workflow conditions and display elements.

4

Create SetKey and IncrKey calls

Add a second call named 'SetKey'. Set method to GET, endpoint to `/set/{{key}}/{{value}}`. Add an optional query parameter: key `ex`, value `{{ttl}}` (TTL in seconds, default `3600`). Initialize the call — it returns `{"result":"OK"}`. This confirms the value was stored. Set 'Use as' to 'Action' since SetKey is a write operation you trigger from workflows, not a data source you bind in the UI. Add a third call named 'IncrKey'. Set method to GET, endpoint to `/incr/{{key}}`. Initialize — it returns `{"result":1}` (the new counter value after incrementing). Set 'Use as' to 'Action'. Optionally, add a fourth call 'ExpireKey': GET `/expire/{{key}}/{{seconds}}` for setting TTL on existing keys (used alongside INCR for rolling rate-limit windows). All four calls use GET method — this is the defining feature of Upstash's REST API and the reason it works with Bubble where standard Redis clients do not. Never set these calls to POST — doing so returns 404 errors.

upstash-write-calls.json
1// SetKey call
2{
3 "method": "GET",
4 "endpoint": "/set/{{key}}/{{value}}",
5 "query_params": [
6 { "key": "ex", "value": "{{ttl}}", "default": "3600" }
7 ]
8}
9
10// IncrKey call
11{
12 "method": "GET",
13 "endpoint": "/incr/{{key}}"
14}
15
16// ExpireKey call
17{
18 "method": "GET",
19 "endpoint": "/expire/{{key}}/{{seconds}}"
20}

Pro tip: Use underscore-separated key names in your Bubble workflows: `cache_product_123` or `rate_limit_user_abc`. Avoid colons, slashes, or spaces in key names — these characters in the URL path cause '404 Not Found' errors from Upstash even though the token and URL are correct.

Expected result: You have four working Upstash API Connector calls: GetKey (Data), SetKey (Action), IncrKey (Action), ExpireKey (Action). All use GET method. You can see them listed under the Upstash Redis API group in your API Connector plugin.

5

Build a cache-first Bubble workflow for expensive API calls

This step shows the core Upstash caching pattern in Bubble workflows. Suppose you call a slow third-party API (e.g., a product catalog API) on page load. Open your Bubble workflow editor and create a 'Page is loaded' event workflow. Step 1: Run 'Get data from an external API' → select GetKey → set `key` to `cache_products` (or a dynamic key per user). Step 2: Add a condition branch using 'Only when' on an action: check if the GetKey result's `result` field is not empty. If it IS empty (null), proceed to Step 3. If it has a value, jump to Step 5. Step 3 (cache miss): Call your real third-party API workflow. Step 4: Run SetKey — set `key` to `cache_products`, `value` to the serialized API response, `ttl` to `3600`. Step 5 (both paths converge): Populate your Bubble data source from either the cached or fresh response. This pattern means Bubble only calls the expensive external API once per hour. Measure your Bubble WU consumption before and after enabling the cache to verify savings — the cache is most valuable when the external call is slow and runs on every page load.

Pro tip: For the RapidDev team, implementing caching layers in Bubble is one of the most impactful performance optimizations in production apps — especially for apps that aggregate data from multiple external APIs. If you are building a data-heavy Bubble app and want to avoid runaway WU costs, RapidDev's team has hands-on experience building these patterns at scale. Free scoping call at rapidevelopers.com/contact.

Expected result: The page load workflow checks Upstash first on every load. On a cache hit, the third-party API call is skipped entirely. On a cache miss, the real API is called and the result is stored in Upstash for the next hour. Your Repeating Group or display element populates correctly in both paths.

6

Build a rate-limiting workflow using INCR and EXPIRE

Rate limiting prevents a user from submitting a form, clicking a button, or triggering an action more than N times within a rolling window. In your Bubble workflow editor, create a workflow triggered by a button click (e.g., 'Submit form'). Step 1: Run IncrKey with `key` set to `rate_limit_` + the current user's unique ID (combine 'rate_limit_' text with the Current User's Unique ID field in Bubble's expression builder). The result comes back as a number in the `result` field. Step 2: Add a conditional action that only runs 'Only when IncrKey's result = 1' — run ExpireKey with the same key and `seconds` set to `3600`. This sets the rolling 1-hour window on the first use. Step 3: Add a condition on all subsequent form steps 'Only when IncrKey's result ≤ 5' (or your chosen limit). Step 4: If the count exceeds 5, show an alert popup with an error message and stop the workflow using the 'Terminate this workflow' action. If within the limit, proceed with the form submission steps. Remember: key names must be URL-safe. Construct your key as `rate_limit_` followed by the user ID — do not include email addresses or special characters in key names.

Pro tip: Upstash's free tier of 10,000 commands per day can fill quickly if every button click on a busy app runs INCR + EXPIRE. For high-traffic apps, check the Upstash command count in your dashboard daily for the first week and upgrade to pay-as-you-go before the limit causes failures.

Expected result: The rate-limit workflow correctly blocks users after exceeding the threshold within the rolling hour window. The EXPIRE call runs only on the first increment, setting the window. Subsequent increments within the window count toward the limit without resetting it. After the hour expires, the key disappears and the counter resets to zero on the next action.

Common use cases

Cache slow third-party API responses

Your Bubble app calls a weather, stock, or product pricing API on every page load, consuming both Workload Units and external API quota. Store the JSON response in Upstash with a 3600-second TTL using SetKey. On subsequent loads, GetKey first — if the result is not null, use the cached value and skip the external call entirely. This can reduce Bubble WU consumption significantly for high-traffic pages.

Bubble Prompt

Build a Bubble workflow that checks Upstash for a cached weather response for a city before calling the OpenWeather API. If the cache returns null, call OpenWeather, store the result in Upstash with a 1-hour TTL, and display it. If the cache has a value, display it directly.

Copy this prompt to try it in Bubble

Per-user rate limiting for form submissions

Prevent spam or abuse by limiting how many times a user can submit a form within an hour. On each submission, increment an Upstash counter keyed by the user's ID (INCR) and set a 3600-second expiry on the first increment (EXPIRE). Compare the returned count to your threshold in a Bubble condition — if exceeded, show an error message and halt the workflow without processing the submission.

Bubble Prompt

Create a Bubble workflow that uses Upstash INCR to count how many times a user has submitted a contact form in the last hour. If the count exceeds 5, display an alert and stop the workflow. If it is exactly 1 (first submission), also run the EXPIRE call to set the 1-hour rolling window.

Copy this prompt to try it in Bubble

Session flags and one-time popups

Track lightweight session state that does not need to persist in Bubble's database — such as whether a user has already seen an onboarding modal in their current session. Store a flag in Upstash with a short TTL tied to the user's session identifier. On page load, GetKey checks the flag; if absent, show the modal and SetKey to suppress it for the rest of the session.

Bubble Prompt

Set up a Bubble page load workflow that calls Upstash GetKey with the current user's ID as the key. If the result is null, show the onboarding popup and call SetKey to store 'seen' with a 1800-second TTL. If the result is 'seen', skip the popup entirely.

Copy this prompt to try it in Bubble

Troubleshooting

Initialize call returns 'There was an issue setting up your call' or 404 error

Cause: The most common cause is using the wrong HTTP method. Upstash REST uses GET for every command including SET, INCR, and DEL. If you set a call to POST or PUT, Upstash returns 404. A second common cause is a missing space between 'Bearer' and your token in the Authorization header value.

Solution: Check that every Upstash API Connector call uses the GET method. Verify your Authorization header value is exactly `Bearer ` followed immediately by your token with a single space between them. Also confirm your root URL does not have a trailing slash — it should end with `.upstash.io` not `.upstash.io/`.

SetKey call returns 404 but GetKey works fine

Cause: The SetKey endpoint includes the value in the URL path (`/set/{{key}}/{{value}}`), so a value containing slashes, spaces, or special characters breaks the URL structure. Bubble passes the value raw into the path.

Solution: URL-encode the value before passing it to SetKey, or restrict cached values to JSON strings without unescaped special characters. For simple strings and JSON blobs, ensure they are serialized as compact JSON (no line breaks). If you need to cache complex data, consider base64-encoding the value first using Bubble's 'Encode text' operator.

Rate limit counter does not reset after an hour — users stay blocked indefinitely

Cause: The ExpireKey call is missing or is running with `key` as a hardcoded string instead of the dynamic user-specific key. If the key never receives an EXPIRE command, it persists in Upstash forever (or until manually deleted).

Solution: Confirm that your ExpireKey call runs with the 'Only when IncrKey's result = 1' condition so it fires on the first increment. Verify the `key` parameter in the ExpireKey call matches the exact same dynamic expression as IncrKey — both must include the Current User's Unique ID. Test by incrementing the counter manually in the Upstash console and confirming the TTL appears.

Upstash commands stop working mid-day with 429 errors

Cause: Your Bubble app has exhausted the Upstash free tier of 10,000 commands per day. If caching is called on every page load without checking Bubble's App State first, command count accumulates faster than expected.

Solution: Upgrade to Upstash's pay-as-you-go plan for production apps. As a short-term fix, cache Upstash results in Bubble's App Data or custom states within a session so repeated page navigations within the same session do not re-call Upstash. Check the command count in your Upstash console to understand usage patterns before optimizing.

Best practices

  • Always mark the Upstash REST Token as Private in the Bubble API Connector shared header. The token grants full database access including destructive commands — exposing it client-side would allow any user to delete your entire cache.
  • Use underscore-separated key names (cache_product_123, rate_limit_user_abc) and never include colons, slashes, spaces, or user-supplied strings directly in key names without sanitization.
  • Set a TTL on every cached key using the `ex` parameter on SetKey. Keys without TTLs accumulate indefinitely and consume storage quota. A 3600-second (1-hour) TTL is a sensible starting point for most cached API responses.
  • Cache Upstash responses in Bubble's App State or custom states within a user session. If the same page navigates between sub-pages, re-calling Upstash on each sub-page visit wastes commands against your daily quota.
  • Measure Bubble Workload Unit (WU) consumption before and after adding a caching layer. Open the Logs tab in your Bubble editor to view WU usage per workflow run. Caching only provides value if the cached call is slower or more expensive than the cache lookup.
  • For scheduled cache-warming workflows (pre-populating Upstash before peak traffic hours), use Bubble's API Workflows with 'Schedule API workflow' — note this requires a paid Bubble plan (Starter or above).
  • Design key namespaces to avoid collisions across different Bubble app features. Use a prefix per feature: `cache_` for cached responses, `rate_` for rate limiters, `flag_` for session flags. Document the naming convention in your Bubble app's Settings → General → App description for future team members.

Alternatives

Frequently asked questions

Why does Upstash use GET for SET and INCR commands? That seems backwards.

Upstash's REST API maps every Redis command to a URL path for simplicity. `/set/{key}/{value}` stores a value, `/incr/{key}` increments a counter — all via HTTP GET. This is intentional: it allows any HTTP client (including Bubble's API Connector, browser fetch, and curl) to run Redis commands without special client libraries. The trade-off is that values in the URL path are limited to URL-safe strings. For write operations with complex values, Upstash also supports POST with a JSON body — but the GET approach is simpler for most Bubble use cases.

Can I use standard Redis with Bubble instead of Upstash?

No. Standard Redis requires a persistent TCP connection over port 6379 using the Redis Serialization Protocol (RESP) — a binary protocol that Bubble's API Connector cannot initiate. Upstash is the practical solution for Bubble because it exposes Redis commands as plain HTTPS GET requests. If you already have a self-hosted Redis instance, you can deploy a thin REST proxy (e.g., a Render Node.js service using the `ioredis` package) that translates HTTPS calls into Redis commands — but Upstash eliminates this complexity for most use cases.

Do API Workflows (scheduled workflows) in Bubble work with Upstash?

Upstash itself works the same whether called from a Bubble front-end workflow or a Backend API Workflow. The limitation is Bubble-side: API Workflows (including the 'Schedule API workflow' action and recurring events) require a paid Bubble plan (Starter or above) and are not available on the Free plan. If you need to warm your Upstash cache on a schedule (e.g., pre-loading product data every hour), you need at minimum a Bubble Starter plan.

Is Upstash's free tier enough for a production Bubble app?

The Upstash free tier provides 10,000 commands per day, resetting at midnight UTC. For a low-traffic Bubble app or during development this is adequate. A production app with meaningful traffic can exhaust this quickly — particularly if GetKey runs on every page load without session-level caching in Bubble's App State. Monitor your command count in the Upstash console during your first week of traffic and upgrade to pay-as-you-go before hitting the limit, as 429 errors will cause your caching workflows to fail silently.

How do I delete a cached key from Upstash in a Bubble workflow?

Add a new API Connector call named 'DeleteKey' with method GET and endpoint `/del/{{key}}`. Initialize it — it returns `{"result":1}` if the key was deleted or `{"result":0}` if the key did not exist. Call this in a Bubble workflow whenever you need to invalidate a cached value — for example, after a user updates their profile, delete the `cache_user_{id}` key so the next page load fetches fresh data.

What happens to my Upstash data if I exceed the free tier limit?

Upstash stops accepting new commands (returns 429 Too Many Requests) once you exceed the daily free tier command count. Existing data in the database is not deleted. Your Bubble workflows that call Upstash will receive error responses, which you should handle with Bubble's 'Step is not run' condition or a fallback pathway that calls the real API directly. Upgrade to pay-as-you-go in the Upstash console to restore service — the upgrade takes effect immediately.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Bubble integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.