Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component is only used in the Build component, which is only returned from "get build", "build actor" and "abort actor build" endpoints - its that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct

Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ properties:
dataset:
type: object
description: Defines the schema of items in your dataset, the full specification can be found in [Apify docs](https://docs.apify.com/platform/actors/development/actor-definition/dataset-schema)
defaultMemoryMbytes:
oneOf:
- type: string
example: get(input, 'startUrls.length', 1) * 1024
- type: integer
example: 1024
description: Specifies the default amount of memory in megabytes to be used when the Actor is started. Can be an integer or a dynamic memory expression.
minMemoryMbytes:
type: integer
minimum: 256
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import TabItem from '@theme/TabItem';
"name": "name-of-my-scraper",
"version": "0.0",
"buildTag": "latest",
"defaultMemoryMbytes": "get(input, 'startUrls.length', 1) * 1024",
"minMemoryMbytes": 256,
"maxMemoryMbytes": 4096,
"environmentVariables": {
Expand Down Expand Up @@ -66,7 +67,7 @@ Actor `name`, `version`, `buildTag`, and `environmentVariables` are currently on

| Property | Type | Description |
| --- | --- | --- |
| `actorSpecification` | Required | The version of the Actor specification. This property must be set to `1`, which is the only version available. |
| `actorSpecification` | Required | The version of the Actor specification. This property must be set to `1`, which is the only version available. |
| `name` | Required | The name of the Actor. |
| `version` | Required | The version of the Actor, specified in the format `[Number].[Number]`, e.g., `0.1`, `0.3`, `1.0`, `1.3`, etc. |
| `buildTag` | Optional | The tag name to be applied to a successful build of the Actor. If not specified, defaults to `latest`. Refer to the [builds](../builds_and_runs/builds.md) for more information. |
Expand All @@ -77,6 +78,7 @@ Actor `name`, `version`, `buildTag`, and `environmentVariables` are currently on
| `input` | Optional | You can embed your [input schema](./input_schema/index.md) object directly in `actor.json` under the `input` field. You can also provide a path to a custom input schema. If not provided, the input schema at `.actor/INPUT_SCHEMA.json` or `INPUT_SCHEMA.json` is used, in this order of preference. |
| `changelog` | Optional | The path to the CHANGELOG file displayed in the Information tab of the Actor in Apify Console next to Readme. If not provided, the CHANGELOG at `.actor/CHANGELOG.md` or `CHANGELOG.md` is used, in this order of preference. Your Actor doesn't need to have a CHANGELOG but it is a good practice to keep it updated for published Actors. |
| `storages.dataset` | Optional | You can define the schema of the items in your dataset under the `storages.dataset` field. This can be either an embedded object or a path to a JSON schema file. [Read more](/platform/actors/development/actor-definition/dataset-schema) about Actor dataset schemas. |
| `defaultMemoryMbytes` | Optional | Specifies the default amount of memory in megabytes to be used when the Actor is started. Can be an integer or a [dynamic memory expression string](./dynamic_actor_memory/index.md). |
| `minMemoryMbytes` | Optional | Specifies the minimum amount of memory in megabytes required by the Actor to run. Requires an _integer_ value. If both `minMemoryMbytes` and `maxMemoryMbytes` are set, then `minMemoryMbytes` must be equal or lower than `maxMemoryMbytes`. Refer to the [Usage and resources](https://docs.apify.com/platform/actors/running/usage-and-resources#memory) for more details about memory allocation. |
| `maxMemoryMbytes` | Optional | Specifies the maximum amount of memory in megabytes required by the Actor to run. It can be used to control the costs of run, especially when developing pay per result Actors. Requires an _integer_ value. Refer to the [Usage and resources](https://docs.apify.com/platform/actors/running/usage-and-resources#memory) for more details about memory allocation. |
| `usesStandbyMode` | Optional | Boolean specifying whether the Actor will have [Standby mode](../programming_interface/actor_standby.md) enabled. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
---
title: Dynamic Actor memory
description: Learn how to automatically adjust your Actor's memory based on input size and run options, so you can optimize performance and reduce costs without manual configuration..
slug: /actors/development/actor-definition/dynamic-actor-memory
---

**Learn how to automatically adjust your Actor's memory based on input size and run options, so you can optimize performance and reduce costs without manual configuration.**

---

Dynamic Actor memory allows Actors to _automatically adjust its memory allocation based on the input and run options_. Instead of always using a fixed memory value, Actor can use just the right amount of memory for each run.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(opt) Maybe provide a quick example? Might help with understanding the feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, added example to introduction


This helps:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) This is kind of overlapping with Why dynamic memory matters.


- _Optimize performance_ for large inputs (more memory for bigger tasks).
- _Reduce costs_ for small runs (less memory when it’s not needed).
- _Provide better user experience_, so users get optimal performance without having to manually configure memory.

:::info
_Important_: The memory calculated by dynamic expression is used as the default memory for the run. Users can still override it manually for each run.
:::

---

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(opt) I'm kind of missing here a section How dynamic memory works.

First of all, we should double-down on the fact that dynamic does not mean that the Actor can on-the-fly ask for more memory. IMHO this is easily confused (we have seen it even internally).

Second, it should explain the whole "memory configuration pipeline", as in, how is memory for a run determined (memory expression vs Actor defaults vs run overrides).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, refactored it 👍

## Why dynamic memory matters

Currently, Actors often use a _static default memory_, but the optimal memory usually depends on the input:

- A small input (e.g., 10 URLs) might run fine on 512 MB.
- A large input (e.g., 1,000 URLs) could require 4 GB+ to run efficiently.

Setting a single default either _wastes resources or slows down execution_. Dynamic memory solves this by calculating memory just before the run starts.

---

## How to define dynamic memory expression

You can define a dynamic memory expression in your `actor.json`:

```json
{
"defaultMemoryMbytes": "get(input, 'startUrls.length' * 1024)"
}
```

- The expression is evaluated _before the run starts_.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) This is not really related how to define the expression, but rather how it works. See my suggestion above.

- The expression can reference variables from input and run options to calculate memory (e.g., `input.startUrls`, `runOptions.maxItems`).
- The result becomes the default memory for the run, but users can still override it.

---

### Writing Expressions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) I don't think you need this headline, it can be merged with the previous section.


Expressions are based on [MathJS](https://mathjs.org/), extended with custom helper function `get`.

#### Variable Access
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### Variable Access
#### Variable access

This is forbidden by our style-guide. If you use LLMs to write the docs, let it follow the guide 😝


You can access variables in two ways:

1. Direct property access

```js
input.foo + 512
runOptions.maxItems + 256
```

1. Double-brace syntax

```js
{{input.foo}}
{{runOptions.maxItems}}
```

_You can mix both styles._

#### Supported Operations

- Arithmetic: `+`, `-`, `*`, `/`
- Math functions: `min()`, `max()`, `ceil()`, `floor()`, `round()`, `log()`, `exp()`, `log10()`
- Conditional logic:

```js
condition ? valueIfTrue : valueIfFalse
```

- Variable assignment:

```js
memoryPerUrl = 64;
get(input, 'startUrls') * memoryPerUrl
```

#### Custom `get()` function

Use `get()` to safely read nested properties or provide fallback values:

```js
get(obj, 'path.to.property', defaultValue)
```

Examples:

```js
// Safely get array length
get(input, 'startUrls.length', 1) // returns length or 1 if undefined

// Safely get nested property
get(input, 'foo.bar.baz.count') // safely access nested objects

// Fallback
get(input, 'foo', 1024) // returns 1024 if 'foo' doesn't exist

// Safely get an array element
get(input, 'numbers.1') // element at index 1 of the numbers array
```

### Memory limits and clamping

After evaluation:

1. The result is rounded up to the nearest power of two

- 900 → 1024 MB
- 3,600 → 4096 MB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it clear that this is not always rounding up.


1. It is clamped to actor-defined min/max (`minMemoryMbytes` / `maxMemoryMbytes`).
2. It is clamped to platform limits (128 MB to 32 GB).

:::info
If the calculation results in an error, the Actor will start with a fixed default memory, which can be configured in the Actor's UI settings.
:::

### Example expressions

#### Simple memory based on URL count

```js
get(input, 'startUrls.length', 1) * 512
```

#### Conditional logic

```js
get(input, 'scrapeDetailed', false) ? 4096 : 1024
```

#### More complex calculation

```js
urls = get(input, 'startUrls.length', 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
urls = get(input, 'startUrls.length', 0);
urlCount = get(input, 'startUrls.length', 0);

reviewsMultiplier = max(get(input, 'maxReviews', 1) / 10, 1);
urls * reviewsMultiplier * 128
```

#### Using double-brace variables

```js
{{input.itemsToProcess}} * 64
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use Tabs component here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, refactored it


### Testing expressions

#### Use npm package

You can use our [npm package](https://www.npmjs.com/package/@apify/actor-memory-expression) not only to calculate memory for your expression, but also to write unit tests and verify the behavior of your expressions locally.

```shell
npm install @apify/actor-memory-expression
```

```js
import { calculateRunDynamicMemory } from '@apify/actor-memory-expression';

await calculateRunDynamicMemory(
"get(input, 'urls.length', 1) * 256",
{
input: { urls: ["a", "b", "c"] },
runOptions: { maxTotalChargeUsd: 10 }
}
);
```

#### Use CLI

You can use [Apify CLI](https://docs.apify.com/cli) to quickly evaluate expressions without writing code. It supports reading input from a JSON file and passing run options as flags.

```shell
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not correct language declaration for code block. IIRC it's based on Prism.js and in such cases bash is generally used (this is valid for whole document)

apify actor calculate-memory --input ./input.json --maxTotalChargeUsd=25
```

---
Copy link
Contributor

@TC-MO TC-MO Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why there are these lines to break the page? we do it once to at the beginning usually to provide TL:DR of what the page is about but do not use it later for page break

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


### Key Takeaways
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(opt) Is this needed? Is such a section something that we usually do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really, and even if we would do it it shouldn't have been in Title case rather in Sentence case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed key takeaways


- Dynamic memory _automatically adjusts memory_ based on input and run options.
- The result is used as default memory, but users can override it.
- Use `get()`, arithmetic, math functions, and conditional logic to define expressions.
- Test expressions locally with the npm package or CLI.
3 changes: 3 additions & 0 deletions sources/platform/actors/running/input_and_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ As part of the input, you can also specify run options such as [Build](../develo
| Timeout | Timeout for the Actor run in seconds. Zero value means there is no timeout. |
| Memory | Amount of memory allocated for the Actor run, in megabytes. |

:::info Dynamic memory
If the Actor is configured by developer to use [dynamic memory](../development/actor_definition/dynamic_actor_memory/index.md), the system will calculate the optimal memory allocation based on your input. In this case, the **Memory** option acts as an override - if you set it, the calculated value will be ignored.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If the Actor is configured by developer to use [dynamic memory](../development/actor_definition/dynamic_actor_memory/index.md), the system will calculate the optimal memory allocation based on your input. In this case, the **Memory** option acts as an override - if you set it, the calculated value will be ignored.
If the Actor is configured by developer to use [dynamic memory](../development/actor_definition/dynamic_actor_memory/index.md), the system will calculate the optimal memory allocation based on your input. In this case, the **Memory** option acts as an override if you set it, the calculated value will be ignored.

:::

## Output

Expand Down
2 changes: 1 addition & 1 deletion sources/platform/actors/running/usage_and_resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Check out the [Limits](../../limits.md) page for detailed information on Actor m

### Memory

When invoking an Actor, the caller must specify the memory allocation for the Actor run. The memory allocation must follow these requirements:
When invoking an Actor, the caller can specify the memory allocation for the Actor run. If not specified, the Actor's default memory is used (which can be [dynamic](../development/actor_definition/dynamic_actor_memory/index.md)). The memory allocation must follow these requirements:

- It must be a power of 2.
- The minimum allowed value is `128MB`
Expand Down
Loading