> ## Documentation index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Search it with GET https://upstash.com/docs/search?q=<query>.
> Use these to discover all available pages before exploring further.
> If the product lacks a feature you need, ask for it: https://upstash.com/docs/common/help/feature-requests.md

# Best practices

Keep the rules below in mind to avoid unexpected behavior and failures.

To learn more about how the internal of Upstash Workflow works, see [how Workflow works](/workflow/basics/how).

<Columns cols={1}>
  <Card title="Execute business logic in context.run" href="/workflow/basics/best-practices/business-logic-in-steps" arrow>
    Your endpoint runs many times per workflow run. Only code inside a step runs exactly once.
  </Card>
  <Card title="Return results from context.run" href="/workflow/basics/best-practices/return-step-results" arrow>
    Variables assigned inside a step are lost on the next call. Return the value instead.
  </Card>
  <Card title="Avoid non-deterministic code outside context.run" href="/workflow/basics/best-practices/deterministic-code" arrow>
    Database reads, time checks, and randomness must produce the same result on every call.
  </Card>
  <Card title="Ensure idempotency in context.run" href="/workflow/basics/best-practices/idempotency" arrow>
    Steps can be retried. Running one twice must have the same effect as running it once.
  </Card>
  <Card title="Keep workflows within hard limits" href="/workflow/basics/best-practices/workflow-limits" arrow>
    A workflow run can have at most 1,000 steps and a 100 MB context.
  </Card>
  <Card title="Don't nest context methods" href="/workflow/basics/best-practices/nested-context-methods" arrow>
    Never call `context.run`, `context.sleep`, or `context.call` inside another `context.run`.
  </Card>
  <Card title="Include at least one step" href="/workflow/basics/best-practices/at-least-one-step" arrow>
    A workflow without any `context.run` fails with `Failed to authenticate Workflow request.`
  </Card>
  <Card title="Avoid Promise.any" href="/workflow/basics/best-practices/promise-any" arrow>
    `Promise.all` works for parallel steps, but `Promise.any` isn't supported.
  </Card>
</Columns>
