Connect from workloads
This page covers how to connect to a MemoryStore instance. It explains how credentials work, why the plain address in the API response is not one your own code can dial, and how to use the TLS endpoint that is the supported route today.
Read What can actually reach port 6379 before you write any connection code. That is the part that catches everyone.
The curl tabs use the same three variables as the quickstart. The platformctl tabs need none of them.
export MS="https://api.codyhill.dev" # MemoryStore is served on the shared public API
export CAI_PROJECT="00000000-0000-0000-0000-000000000000" # your project UUID
export CAI_TOKEN="<your session token or API key>"
Read the connection details
Every read of an instance returns a connection block:
{
"connection": {
"host": "<private-hostname>",
"port": 6379,
"username": "default",
"credential_secret": "ms-cache-credential"
}
}
Assembled as a URI, that's:
redis://:<password>@<private-hostname>:6379
Three things to understand about it:
- The hostname is private, and it is opaque. It resolves only inside the platform — your laptop cannot reach it, and there is no public endpoint. Read it from the
hostfield on every start rather than hardcoding it or building it from the instance name. The shape is internal and we change it; the field is the contract. - Port 6379 is firewalled, including from your own workloads. This is the surprise on this page, and the next section is entirely about it. Read it before you write any connection code.
- The password is not in this response. A read returns only the name of the Secret that holds it:
ms-<name>-credential, whose keys arepasswordanduri. The value itself is never returned.
What can actually reach port 6379
The platform writes an inbound firewall rule into every project, and you cannot edit it. The rule lets your project's workloads reach each other on the platform's own ports: TCP 8080, 8012, 8022, 9090, and 9091. 6379 is deliberately not on that list. See Workload networking for the full rule.
Port 6379 on a MemoryStore instance is opened for exactly two peers, both of them platform components:
| Peer | Why | When |
|---|---|---|
| The platform's MemoryStore control plane | Reads the instance's live INFO for the stats panel and platformctl memorystore stats | Always |
| The platform's shared data gateway | Terminates TLS for the rediss:// endpoint | Only when you turn on external exposure |
Your own agents, functions, and services are not on that list.
Take connection.host, open a plain connection to port 6379 from an agent, a function, or a serverless service, and the firewall drops the packets. Nothing answers, so your client hangs until its own timeout fires. You usually see that as a connect timeout after 30 seconds or more. No platform log line explains it, and nothing in the API response hints at it.
The API makes this easy to walk into. A create response labels its uri field the internal connection string, and that address really is correct. The firewall in front of it is a separate rule, and the field cannot know about it. So treat the plain uri as the address the platform's own components use — not as one your code can dial.
What to do instead: turn on the optional TLS endpoint and connect through that. It is the supported way to reach your own MemoryStore instance, and Connect over TLS below walks through it.
Manage the one user and its password
MemoryStore has exactly one user, named default. There is no access-control list to manage, so you cannot create extra users with narrower permissions. The password is the whole story:
- The platform generates it at create time and shows it once, in the create response (see the quickstart).
- Every later read returns only
credential_secret, which is the name of the Secret holding it. - Admins can replace it, and the replacement is shown once, the same way.
There are two ways to replace it, and they are not interchangeable. Renewal is the routine refresh for a password that is merely aging out: the new password is added to the live instance, no restart, and the previous one keeps working for a bounded overlap so running clients switch on their own schedule. Rotation is the hard cutover for a password you believe is leaked.
- platformctl
- curl
- Console
platformctl memorystore renew-credential cache # routine, no downtime
platformctl memorystore rotate-credential cache # hard cutover, restarts the instance
Both print the new password on its own line, with the server's note underneath explaining that this is the only response that will ever contain it.
curl -sX POST "$MS/v1/projects/$CAI_PROJECT/memorystores/cache/renew-credential" \
-H "Authorization: Bearer $CAI_TOKEN"
curl -sX POST "$MS/v1/projects/$CAI_PROJECT/memorystores/cache/rotate-credential" \
-H "Authorization: Bearer $CAI_TOKEN"
Both are plain trailing path segments, not the :verb custom methods VectorDB and Pub/Sub use. Both need the project admin role, like every endpoint that returns a credential.
Open the instance. Renew credential and Rotate credential are both on its page, and the new password appears in a copy-once dialog with the same Store in project Secrets offer the create dialog makes.
Rotation does not take effect instantly. The server reads its password once when it starts, so a new password only applies after the instance restarts. The platform triggers that restart for you. Until it finishes, the old password is still the one that works — write your retry logic with that in mind. Renewal applies the new password immediately without requiring a container restart.
Rotating before the instance has finished provisioning fails cleanly:
{"error":"this memorystore has no credential yet; wait for it to finish provisioning","request_id":"..."}
Connect over TLS (the supported route)
Because port 6379 is closed to your own code, the TLS endpoint is how you use an instance. You turn it on per instance, and only at create time.
Step 1 — create the instance with external exposure on
- platformctl
- curl
- Console
platformctl memorystore create cache --external
The create response prints the password once, and adds an external uri line beside the internal uri as soon as the outside address exists. That line is printed only when there really is one, so its absence right after create means the route is still being built.
curl -sX POST "$MS/v1/projects/$CAI_PROJECT/memorystores" \
-H "Authorization: Bearer $CAI_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"cache","external_exposure":true}'
The credential block in the response carries an external_uri with the password already in it, alongside the internal uri.
In the Create a MemoryStore instance dialog, tick Expose externally (TLS rediss://). The confirmation tells you the public address will appear on the instance's own page once it is ready.
The MemoryStore API has no update route. Create, get, list, stats, renew-credential, rotate-credential, and delete are the entire surface, and none of them edits an existing instance. So if you created an instance without external exposure, you cannot switch it on later. You have to create a new instance with the flag set and move your data across. Decide before you create.
Once the route is programmed, the instance reports:
{
"external_exposure": true,
"externally_reachable": true,
"external_endpoint": "rediss://cache-<short>.<domain>:443",
"reachable_scope": "internet"
}
- The endpoint speaks TLS on port 443. TLS is the same encryption that puts the "s" in
https; in Redis addresses it shows up asrediss://, with a doubles. The platform's shared data gateway decrypts your TLS connection and then talks unencrypted to your instance on the internal network. - This address is reachable from the internet. The password is therefore the entire boundary in front of your data, which is why it expires, renews without downtime, and reports every use. To narrow the networks that may reach the address at all, add an address allow list to its endpoint. (
reachable_scopesaysinternet, which is the same fact in one word. It saidvpcuntil private-by-default landed; that was wrong.) - The same
defaultuser and password apply. external_endpointappears only once the cache actually has an outside address — either the instance opted in and its route is built, or you published an endpoint for it. If it is missing right after create, keep re-reading the instance until it shows up.externally_reachableflips totrueat the same moment.
The create and rotate responses also hand back a ready-made external_uri with the password already in it, so you rarely need to assemble the string yourself.
Step 2 — give your workload the password
Never paste the password into your code. When the console shows you the credential, take its Store in project Secrets offer. That saves the password into your project's Secrets under the suggested name memstore-<instance>-password. Your code then reads it from an environment variable. See Secrets and environment variables for how a secret becomes an environment variable in an agent.
The dialog also shows the full rediss:// URI in a separate one-time box. Treat that string as even more sensitive than the password, because the password is embedded inside it. The Store in project Secrets offer does not save the URI. Copy it yourself if you want it, or rebuild it later from the host and the password.
Step 3 — connect
MemoryStore speaks the Redis protocol, so the standard client for your language works unchanged. The one thing you must do is turn TLS on. In Python:
import os
import redis
r = redis.Redis(
host="cache-x7k2q.codyhill.dev", # external_endpoint, without the rediss:// prefix
port=443,
username="default",
password=os.environ["MEMSTORE_CACHE_PASSWORD"], # injected from your secrets
ssl=True, # the endpoint is TLS-only
)
r.set("greeting", "hello")
print(r.get("greeting")) # b'hello'
If you saved the whole rediss:// URI instead, redis.from_url(os.environ["MEMSTORE_CACHE_URI"]) does the same job. The redis-py library sees the rediss:// prefix and sets up TLS for you.
From any machine that can reach the internet, redis-cli works the same way:
redis-cli --tls -h cache-<short>.<domain> -p 443 -a "$MS_PASSWORD" PING
You should see:
PONG
The rediss:// endpoint is proven from a client outside the platform. Whether a platform workload can also dial it back in through the external address is not something the platform reports either way, so do not assume it.
So make your very first call a PING with a short timeout, and log the result. That beats discovering the answer inside a live request handler. If the PING times out, the network path is the problem, not your password.
If none of this works for your case, see support. Use the TLS endpoint for all direct workload connections.
What agents should use instead
People most often want a cache for two things: conversation history and long-term recall. The platform already handles both, with no instance to dial:
| You want | Use this |
|---|---|
| Conversation history across turns | The built-in session store — automatic, nothing to wire up |
| Long-term "what do you know about me" recall | The agent memory bank — vector search, also automatic |
| Your own cache or counters, from a platform workload | The TLS endpoint above, after you have tested reachability |
| Your own cache, from a machine outside the platform | The TLS endpoint above — this is the proven case |
Agents run with an environment variable named CRUSOE_MEMORYSTORE_ADDR. It points at the platform's shared session store, which is the store that holds agent conversation sessions. It does not point at any MemoryStore instance you created, and it is not a back door to one. See Use with agents for the full story.
Connection checklist
| From | Address | Protocol | Works today? |
|---|---|---|---|
Any machine on the internet (with external_exposure on) | rediss://<name>-<short>.<domain>:443 | TLS, user default + password | Yes — the proven path, and the password is the only gate |
| Agents, functions, services in your project | rediss://<name>-<short>.<domain>:443 | TLS, user default + password | Test it first — see the warning above |
| Agents, functions, services in your project | <private-hostname>:6379 | redis:// plaintext | No — blocked by the project firewall |
The public internet, with external_exposure off | — | — | No — nothing is exposed until you turn it on |
Next steps
- Use with agents — the shared session store vs. your instances.
- Secrets and environment variables — wiring passwords into agents properly.
- API reference — rotate-credential, stats, and every field.