---
title: "Finisher"
manual: "Form Rate Limit"
version: "main"
permalink: "https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:finisher@main"
source: "Finisher/Index.rst"
rendered: "2026-09-23T15:53:26+00:00"
---

# Finisher {#finisher}

Target group: **Integrators**

> [!NOTE]
> For now, the finisher can only be integrated directly into the YAML form
> definition and not via the Forms module.

Under the hood, the [symfony/rate-limiter](https://symfony.com/doc/current/rate_limiter.html) is used. This is the same rate
limiter that TYPO3 Core uses to limit the number of incorrect backend logins.

> [!TIP]
> The state of a rate limit for a restriction combination is currently stored
> in the `var/form_rate_limit/` folder. This folder should be shared between
> releases in deployment workflows accordingly.
>
> To clean up the files and free disk storage a [command](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:command@main) is available.

## Example {#example}

Let's start with an example:

```yaml
finishers:
  - identifier: RateLimit
    options:
      policy: 'sliding_window'
      interval: '1 hour'
      limit: 2
      restrictions:
        - '__ipAddress'
        - '__formIdentifier'
        - '{email}'
      template: 'EXT:my_extension/Resources/Private/Templates/Form/RateLimitExceeded.html'

  # other finishers follow
```

The example uses the "sliding window" [policy](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-policy@main). This form
can be submitted successfully twice within one hour from the same IP address
with the same provided email address. Additionally, a custom [template](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-template@main) for the error message is assigned.

> [!WARNING]
> **Attention**
>
> The `RateLimit` finisher should be the first finisher in line.

## Options {#options-interval}

The form finisher ships with default options. If they are suitable for your
needs, you can omit them in your form definition. The default values can be
found in the following list.

-   **interval**

    -   *Type:* string
    -   *Default:* `1 hour`

    The interval for the [policy](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-policy@main) used. Since the interval
    is later passed to the [DateInterval](https://www.php.net/manual/en/dateinterval.createfromdatestring.php#refsect1-dateinterval.createfromdatestring-examples) object, any possible value understood
    by that object is possible, for example:

    -   `2 hours`
    -   `10 minutes`
    -   `1 day`
    -   `1 hour 30 minutes`
    -   `90 minutes`
    -   `PT3600S` (3600 seconds)

-   **limit**

    -   *Type:* int
    -   *Default:* `1`

    The limit to which the form can be submitted with the provided restrictions
    within the specified [interval](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-interval@main).

-   **policy**

    -   *Type:* string
    -   *Default:* `sliding_window`

    Two policies are currently available:

    -   **`fixed_window`**

        This is the simplest technique and it is based on setting a limit for a
        given interval of time (for instance, 5 submits per hour).

        See [Fixed Window Rate Limiter](https://symfony.com/doc/current/rate_limiter.html#fixed-window-rate-limiter) for details.

    -   **`sliding_window`**

        This is similar to the fixed window rate limiter, but then using a 1
        hour window that slides over the timeline.

        See: [Sliding Window Rate Limiter](https://symfony.com/doc/current/rate_limiter.html#sliding-window-rate-limiter)  for details.

    The "token_bucket" policy is currently not supported.

-   **restrictions**

    -   *Type:* array
    -   *Default:* `['__ipAddress', '__formIdentifier']`

    The restrictions for limiting the submission of a form. The default value
    combines the IP address and the form identifier.

    The possible values can be combined at will:

    -   **`__ipAddress`**

        The IP address is taken into account for limiting the submission of a
        form.

    -   **`__formIdentifier`**

        The form identifier is taken into account. This is a combination of the
        identifier in the form definition and the content element ID.

        In connection mode the content element ID is the same for each language.
        In free mode the content element ID is different for each language.

    -   **`{someFormField}`**

        Every form field can be used to add an additional restriction. The field
        identifier must be surrounded by curly brackets.

        For example, if you want to limit the submission to the given email
        address, this field can be added to the restriction list as
        `{email}` if the identifier of the email address field is named
        `email`.

    -   **`someCustomValue`**

        You can set a custom value that will be used unchanged as part of the
        restrictions.

    **Examples:**

    -   Limit by the form and an email address (available as "email" field):

        ```yaml
        restrictions:
           - '__formIdentifier'
           - '{email}'
        ```
    -   Limit by a custom value and some of the defined fields. This may be
        helpful when you have the form multiple times on the website:

        ```yaml
        restrictions:
           - 'our-weekend-raffle'
           - '{name}'
           - '{address}'
           - '{zip}'
           - '{city}'
        ```

-   **template**

    -   *Type:* string
    -   *Default:* `EXT:form_rate_limit/Resources/Private/Templates/RateLimitExceeded.html`

    The extension provides a Fluid template that is used when the rate limit
    is exceeded. You can (and usually want) to customise it to your needs. The
    `template` option gives you the possibility to assign a custom template
    to a finisher. Some variables in the template are available:

    -   **`formIdentifier`**

        The form identifier can be used to insert an anchor into the template. The
        browser will then jump to this anchor in case the rate limit is reached.

    -   **`interval`**

        The configured [interval](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-limit@main) option.

    -   **`limit`**

        The value of the specified [limit](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-limit@main).

    -   **`policy`**

        The defined [policy](https://docs.typo3.org/permalink/brotkrueml/typo3-form-rate-limit:options-policy@main).
