# App authoring limits

Strive validates app definitions before saving or importing them. Use these limits when planning a large app; dividing a complex experience into focused apps and published outputs can keep individual definitions understandable.

| Item | Limit |
| --- | --- |
| Components per definition | 200. |
| Data sources per definition | 50. |
| Published outputs per definition | 50. |
| Events per component | 20. |
| Actions per event | 20. |
| Component/data-source/output id | Starts with a letter, then letters, digits, or underscores; up to 64 characters. |
| Tab/slot id | Lowercase letter first, then lowercase letters, digits, or underscores; up to 32 characters. |
| Container nesting | Four levels; no cycles or invalid parents/slots. |
| Main-grid span | 1–12. |
| Authored input records in a run action | Up to 1,000. |
| Authored trigger-context nesting | Up to 8 levels. |
| Per-source run-check deadline | 1 second to 2 hours; default 5 minutes. |
| Initial post-upload table name | 1–100 characters. |
| Portable app file | 16 MiB. |

Expression bindings have separate resource bounds: 4,096 characters per expression, 256 nesting levels, array lengths up to 50,000, strings up to 262,144 characters, and a bounded evaluation budget. A large expression can exceed that budget even if its text is short.

## Limits are not permissions

A valid id does not grant access to the resource it names. A valid run action still needs a triggerable workflow source and the current host's permission. A valid package still needs compatible destination capabilities and accessible required resources.

## Deadline versus cancellation

The run-check deadline limits how long the app waits to observe completion. It does not cancel the workflow. A timed-out status means **Stopped checking**; inspect the run later to determine whether it completed.

## Recover from a validation problem

Read the reported definition location. Reduce the oversized collection, shorten the expression, remove the invalid reference, or choose a valid value rather than trying to bypass validation with Code view. The destination revalidates the same app configuration.

See [Bindings](/docs/builder/bindings), [Containers](/docs/builder/containers), and [Saving](/docs/builder/saving-and-conflicts).
