---
title: "Frequently asked questions - Workflow Functions"
description: "Common questions about running your own JavaScript from Shopify Flow: plans and quota, permissions, secrets, templates, the developer API, and data handling."
canonical: "https://docs.workflow-functions.app/faq"
---

# Frequently asked questions

Answers to the questions we get most often. If yours is not here, [Run history and troubleshooting](https://docs.workflow-functions.app/run-history-and-troubleshooting.md) covers failures in detail, and [Support](https://docs.workflow-functions.app/help/support.md) has every way to reach us.

### Do I need Shopify Flow?

Yes. Flow is what runs your automation; Workflow Functions adds a **Run Function** action to it so a workflow can execute your code. Flow is free from Shopify. See [Set up the Run Function action in Shopify Flow](https://docs.workflow-functions.app/set-up-the-run-function-action-in-shopify-flow.md).

### What language do I write functions in?

JavaScript or TypeScript. Each function exports a default async function that receives `(input, ctx)` and runs in a secure, isolated sandbox. See [How to create a function](https://docs.workflow-functions.app/how-to-create-a-function.md).

### Do tests count against my plan?

No. Only runs triggered by **Shopify Flow** count against your rolling 30-day quota. The **Test** button in the editor (recorded as *Manual*) and runs through the REST API or MCP (recorded as *API*) are free. A Flow run that fails before your code executes has its quota slot refunded. See [Run history and troubleshooting](https://docs.workflow-functions.app/run-history-and-troubleshooting.md).

### What do the plans include?

Every plan includes all features and unlimited functions - they differ only in how many Flow-triggered runs you get per rolling 30 days: **Free** 500, **Starter** 5,000, **Grow** 15,000, **Unlimited** unlimited. You can watch usage on the dashboard and get emailed at 80% and 100%.

### How does my function read or change store data?

Turn on **Needs Shopify data** for the function, grant the matching permissions on the **Permissions** page, then call `ctx.shopify.graphql(query, variables)` in your code. Your store's access token stays on our server and never enters the sandbox, so it cannot leak into your input, logs or output. See [Permissions and store data access](https://docs.workflow-functions.app/permissions-and-store-data-access.md).

### Why do I see "not approved to access the Customer object"?

Shopify puts the whole Customer object behind its **protected customer data** program, so reading it - even just a customer id - needs an app-level approval that is separate from granting the customers permission in the app. Products, orders and discounts are not affected. If a function needs customer data and hits this error, [Support](https://docs.workflow-functions.app/help/support.md) and we will help - it is not something the Permissions page alone can switch on. See [Permissions and store data access](https://docs.workflow-functions.app/permissions-and-store-data-access.md).

### Can my function use API keys or passwords?

Yes. Store them as **Secrets** and read them in code as `secrets.MY_KEY`. Secrets are encrypted at rest, never shown again after you save them, and their values are masked out of logs, output and run history - so a function can *use* a secret without ever exposing it. See [Creating and using secrets](https://docs.workflow-functions.app/creating-and-using-secrets.md).

### Who can see my function's code?

Anyone with access to the app in your Shopify admin can view and edit every function's code - treat it as shared team code, not a private vault. Keep anything sensitive (API keys, tokens, passwords) in **Secrets** rather than hard-coded in the source; secret values stay masked everywhere. See [Creating and using secrets](https://docs.workflow-functions.app/creating-and-using-secrets.md).

### Can a function call an external API?

Yes. Use `ctx.fetch(url, options)` for outbound HTTP from inside your function - for example to post to Slack, call your own backend, or hit a third-party service. Use `ctx.log(...)` to record what happened; the lines show up on the run detail.

### What is the difference between Test and a real Flow run?

**Test** runs the code currently in the editor against the sample input on the Test tab (recorded as *Manual*, no quota). A real run uses the **saved** function and whatever input Shopify Flow sends it. A green test proves your code works; it does **not** prove the Flow action is wired up correctly, so run the workflow once for real and check History. See [Run history and troubleshooting](https://docs.workflow-functions.app/run-history-and-troubleshooting.md).

### Why did one of my functions get disabled?

You revoked a permission it uses. Revoking a scope automatically disables the functions that depend on it, so they cannot fail half-way through; grant the permission again and they re-enable on their own. You can also toggle **Enabled** yourself on a function's Settings tab. See [Permissions and store data access](https://docs.workflow-functions.app/permissions-and-store-data-access.md).

### Can I share a function with another store, or publish a template?

Templates you save are **private to your store** for now - sharing them publicly between stores is coming. The **Verified** templates from Code Creation Labs are available to every store as a ready-made starting point. See [Using templates](https://docs.workflow-functions.app/using-templates.md).

### How long can a function run, and how much memory does it get?

Set the timeout (up to 30 seconds) and memory (up to 512 MB) per function on its **Settings** tab. A run that exceeds its timeout is recorded as **Timeout** - usually a slow external call or an endless loop. See [Run history and troubleshooting](https://docs.workflow-functions.app/run-history-and-troubleshooting.md).

### Can I manage or run functions from my own code or an AI assistant?

Yes. The **Developer** page issues API keys for a **REST API** and an **MCP server**, so you can list, create, update and run functions from a script or an AI agent. Runs started this way are marked *API* and do not count against your Flow quota. See [Developer API and MCP](https://docs.workflow-functions.app/developer-api-and-mcp.md).

### Does a Flow retry run my code twice?

No. If Flow retries the same action execution, we recognise the duplicate and return the earlier result instead of running your code again - so side effects (like creating a discount) do not repeat, and it does not cost a second quota slot. See [Set up the Run Function action in Shopify Flow](https://docs.workflow-functions.app/set-up-the-run-function-action-in-shopify-flow.md).

### Where is my data stored?

In the EU, encrypted at rest. Secrets get an additional layer of envelope encryption through a dedicated key-management service, are never stored in plaintext, and never appear in run history. Function input and output are kept in History so you can debug and re-run.

## Still need help?

Use the [Support](https://docs.workflow-functions.app/help/support.md) page to report a bug, request a feature, or contact us directly. The in-app chat bubble is on every page of the app and is usually the fastest route, since it keeps the conversation tied to your store.
