# 레이트 리밋

> 폼별 레이트 리밋 프리셋의 정확한 수치, 허용량이 다시 채워지는 방식, 429 응답의 모습.

레이트 리밋은 방문자 한 명이나 스크립트 하나가 폼에 요청을 쏟아붓지 못하게 막습니다. 모든 폼에는 프리셋이 있으며, 모든 한도는 본문을 읽기 전에 정확하게 셉니다. 거부된 POST는 허용량을 소모하지 않습니다.

## 프리셋

| 프리셋 | 방문자와 폼별 | 적합한 용도 |
| --- | --- | --- |
| Standard (기본값) | 분당 5건, 10초에 최대 3건 | 대부분의 폼 |
| Relaxed | 분당 20건 | 로그인 뒤의 폼, 내부 도구, 공용 Wi-Fi를 쓰는 이벤트 |
| Strict | 10분마다 2건 | 반복 요청이 대개 더블 클릭이나 봇인 문의 및 영업 폼 |
| Custom | 10초, 1분, 10분, 1시간, 1일마다 1~1,000건 | 1인 1회 응모, 키오스크 등 특수한 경우 |

## 프리셋 비교

방문자가 2분 동안 1초에 한 번씩 보내기를 누르면 다음과 같이 통과합니다. Ikiform이 실행하는 것과 같은 알고리즘으로 시뮬레이션했습니다.

| 프리셋 | 120건 중 수락 | 수락된 시점(초) |
| --- | --- | --- |
| Standard | 14 | 0, 1, 2, 4, 7, 12, 24, 36, 48, 60, 72, 84, ... |
| Relaxed | 59 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... |
| Strict | 2 | 0, 1 |

## 허용량이 다시 채워지는 방식

한도는 고정된 시간 창이 아니라 부드럽게 채워지는 허용량입니다. 한동안 조용했던 방문자는 허용량이 가득 찬 상태로 시작해 한 번에 다 쓸 수 있습니다. 그 이후에는 시간 창을 한도로 나눈 간격마다 POST가 하나씩 더 허용됩니다. Standard는 12초마다, Relaxed는 3초마다, Strict는 5분마다입니다. 시간 창 하나만큼 조용히 지나면 허용량이 다시 가득 찹니다.

Standard에는 10초에 3건이라는 버스트 규칙도 있어서, 첫 버스트는 5건이 아니라 3건입니다. Relaxed, Strict, Custom에는 별도의 버스트 규칙이 없습니다.

## 항상 적용되는 한도

| 규칙 | 한도 | 집계 기준 |
| --- | --- | --- |
| 플러드 가드, 폼 조회 전 | 분당 600건 | IP, 모든 폼 합산 |
| 폼 간 합산 | 분당 30건, Custom의 분당 비율이 더 높으면 그 값 | IP, 모든 폼 합산 |
| 폼 전체 | 분당 300건, 또는 Custom 상한 1~10,000건 | 폼, 모든 방문자 합산 |
| `GET /f/<formId>/schema` | 분당 60건 | IP와 폼 |
| Ikiform 확인 프레임 | 분당 60건 | IP와 폼 |
| REST API | 분당 100건 | API 키 |

플러드 가드보다 빠른 Custom 비율은 저장할 때 거부됩니다. 예를 들어 10초 창은 최대 100건까지 허용됩니다. 폼의 스키마나 사람 확인을 불러와도 제출 허용량은 소모되지 않습니다.

## Custom

- **방문자별 제출 수:** 1~1,000의 정수와, 10초, 1분, 10분, 1시간, 1일 중 하나의 시간 창.
- **폼 전체 분당 상한:** 선택 사항이며 1~10,000. 폼 전체에 적용되는 기본값 분당 300건을 대체합니다.
- 1시간이나 1일 시간 창은 경품 응모나 참석 확인처럼 1인 1회 폼에 적합합니다. 사무실이나 이벤트처럼 많은 사람이 IP 하나를 공유할 수 있다는 점을 기억하세요.

## 한도에 도달하면

POST는 `429 rate_limited`로 거부되며, 다음 POST가 허용될 때까지 남은 초를 정수로 담은 `Retry-After` 헤더가 붙습니다. 브라우저 폼 POST에는 호스팅된 "Slow down" 페이지가 표시됩니다. Ikiform이 CORS로 노출하므로 `fetch` 코드는 `Retry-After`를 읽을 수 있습니다.

`429 Too Many Requests`:

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-Request-Id: req_01k7v2c9t3e8m5q4x6z0a1b2c3
Content-Type: application/json; charset=utf-8

{"ok":false,"error":{"code":"rate_limited","message":"Too many requests. Please slow down."},"request_id":"req_01k7v2c9t3e8m5q4x6z0a1b2c3"}
```

1. 다시 보내기 전에 `Retry-After` 초만큼 기다리세요.
2. 정상적인 방문자가 한도에 닿는다면 폼을 Relaxed나 Custom으로 바꾸세요.
3. 서버가 방문자 대신 POST한다면 모든 POST가 서버의 IP를 공유합니다. [서버에서 보내기](https://ikiform.com/ko/docs/guides/server.md#what-changes)를 참고하세요.

> 레이트 리밋 설정은 비공개입니다. 스키마 엔드포인트나 REST API로 노출되지 않습니다.
