Waiting Room
Kapasite eşiğini aşan meşru kullanıcıları sıraya alır, tahmini bekleme süresi gösterir ve origin'i ayakta tutar. Bot savunması değil, kapasite yönetimi aracı.
- DurumGenel kullanımda
- FiyatPlana dahil — kullanıcı veya kuyruk başına metered ücret yok
- Doğrulama
Waiting Room nedir?
“Cloudflare Waiting Room allows you to route excess users of your website to a customized waiting room, helping preserve customer experience and protect origin servers from being overwhelmed with requests.”
“Waiting Room queues visitors when your traffic approaches a previously defined threshold that might otherwise bring an application down.”
Resmî fayda listesi, birebir:
“Keeping your application online and preventing them from reaching error pages. · Showing estimated wait times that are continuously updated. · Opening up new spots more quickly by tracking dynamic inflow and outflow. · Remembering each visitor’s status to prevent someone from losing their place in line or having to re-queue if they leave your site. · Appearing in your own branding and style.”
Üç ön koşul
“Cloudflare’s CDN is required to use the Waiting Room feature.”
“Configure a proxied DNS record or a proxied load balancer for the waiting room’s hostname. A DNS record is not auto-configured after a waiting room is created.”
“Visitors must enable cookies.”
Nasıl çalışır?
Mimari — her veri merkezi kendi kararını veriyor
“Waiting Room is built on Workers that runs across a global network of Cloudflare data centers.”
“When a request comes to a host or path covered by a Waiting Room, that request goes to a Waiting Room Worker in the closest geographic data center. The Worker then needs to make a decision: whether to send users to the queue or the website.”
“Each data center works with its own Waiting Room state. This state is a snapshot of the traffic pattern for the website around the world available at that point in time… The algorithm for Waiting Room dynamically allocates a certain number of slots available to each Worker based on the Waiting Room state. Queueing starts when the slots run out within the Worker.”
Senkronizasyon:
“The Waiting Room state is updated with global information every few seconds. We have a pipeline set up in Cloudflare Durable Objects that ensures changes in traffic get propagated around the world.”
Slot dağıtımı — resmî örnek
Kuyruk blogundaki (20 Eylül 2023) örnek durum:
{
"activeUsers": 50,
"globalWorkersActive": 10,
"dataCenterWorkersActive": 3,
"trafficHistory": {
"Mon, 11 Sep 2023 11:44:00 GMT": {
"San Jose": "20/200",
"London": "30/200",
"Anywhere": "150/200"
}
}
}
“Looking at the traffic history for the minute … we see San Jose has 20 users out of 200 users going there (10%) … we divide the slots available at the website at the same ratio as the traffic history in the past minute. So we can send 10% of 150 slots available from San Jose which is 15 users.”
“The number of slots available for the data center is divided evenly among the workers in the data center. So every worker in San Jose can send 15/3 users to the website.”
Yani slotlar önce coğrafyaya, sonra o coğrafyadaki Worker’lara bölünüyor.
Slot aritmetiği — iki eşiğin nasıl birlikte çalıştığı
GA blogundan, birebir:
“Let’s say we deploy a Waiting Room on ‘https://example.com/waitingroom’ that can support 10,000 Total Active Users, and we allow up to 2,000 New Users Per Minute. If there are currently 7,000 active users on the website, we have 10,000 − 7,000 = 3,000 open slots. However, we need to take the minimum (3,000, 2,000) = 2,000 since we need to respect the New Users Per Minute limit.”
Tahmini bekleme süresi nasıl hesaplanıyor
“When a visitor first enters the host and path combination for your waiting room, they receive the
__cfwaitingroomcookie. That cookie contains a unique group ID, which corresponds to the minute your visitor entered the waiting room. Using this value, we can tell how many visitors are in front of a specific group.”
“Each cookie also contains a value for
acceptedAt, which corresponds to the minute your visitor entered your application. This value lets us know how many visitors per minute are leaving the waiting room.”
önündekiSayısı ÷ dakikadaGirenSayısı = tahminiBeklemeSüresi
Ayarların tam listesi
| Panel | API alanı | Zorunlu | Sınır / varsayılan |
|---|---|---|---|
| Name | name | Evet | alfanümerik, tire ve alt çizgi |
| Hostname | host | Evet | wildcard yok, https:// yazma |
| Path | path | Hayır | büyük/küçük harfe duyarlı, wildcard ve query yok |
| Additional Hostnames and Paths | additional_routes | Hayır | Advanced; sonda örtük wildcard var |
| Custom Cookie Suffix | cookie_suffix | additional_routes varsa evet | maks 32 karakter |
| Total active users | total_active_users | Evet | min 200, maks 2147483647 |
| New users per minute | new_users_per_minute | Evet | min 200, ≤ total_active_users |
| Session duration | session_duration | Hayır | 1–30 dakika, varsayılan 5 |
| Disable session renewal | disable_session_renewal | Hayır | Enterprise + satın alma |
| JSON response | json_response_enabled | Hayır | Advanced; varsayılan false |
| Queueing status code | queueing_status_code | Hayır | enum 200 / 202 / 429, varsayılan 200 |
| Session Revocation | enabled_origin_commands | Hayır | ["revoke"], Advanced |
| Turnstile Widget Mode | turnstile_mode | Evet | off · invisible · visible_non_interactive · visible_managed |
| Turnstile Fail Action | turnstile_action | Evet | log · infinite_queue |
| Queue all | queue_all | Hayır | varsayılan false |
| Queueing method | queueing_method | Hayır | varsayılan fifo |
| Suspended | suspended | Hayır | true ise trafik kuyruğa girmiyor |
| Custom HTML | custom_page_html | Hayır | Advanced, maks 1 MB |
| Varsayılan dil | default_template_language | Hayır | 37 locale, tr-TR dahil; yoksa en-US |
Queueing method’lar
| Method | Birebir tanım | Ne zaman |
|---|---|---|
| FIFO | “Your waiting room orders visitors according to when they entered the waiting room.” | “when you want to reward visitors who get in the queue first and wait longer” |
| Random | “your waiting room chooses visitors at random to exit the waiting room” | “when you want to distribute products or services more equitably” |
| Passthrough | “Allow all traffic to pass immediately through… However, analytics will be gathered” | ölçmek ama sıraya almamak |
| Reject | “Prevent any traffic from reaching your application… Users will get a static page.” | “for event-only endpoints or to perform application maintenance” |
Üstünlük kuralı: “Regardless of the queueing method, if queueAll is enabled or an event is
prequeueing, users in the waiting room will not be accepted to the origin.”
reject bir ek davranış taşıyor: “the waiting room page will not refresh automatically” ve JSON
yanıtında refreshIntervalSeconds her zaman 0.
Canlıyken method değiştirmek:
“From FIFO to Random: Users will no longer be ordered based on their cookie timestamp, which may affect the displayed wait time. From Random to FIFO: Users will be ordered based on their cookie timestamp, meaning any new users move to the end of the FIFO queue.”
“If you change the queueing method from FIFO > Random > FIFO, users will be ordered by their original entry time.”
Plan: Business = yalnızca FIFO. Enterprise varsayılan FIFO; Advanced ile dördü de.
Özel şablon — Mustache, 1 MB ve Türkçe sınırı
“The HTML file size limit is 1,048,576 bytes (1 MB).”
“The template is based on mustache.” ve “including raw HTML within your template without escaping requires three curly braces instead of two.”
Sık kullanılan değişkenler:
| Değişken | Birebir açıklama |
|---|---|
{{waitTimeKnown}} | “boolean value that indicates the behavior to take when wait time is not available, for instance when queue_all is true” |
{{waitTimeFormatted}} | “Estimated wait time for the user. For example, five minutes.” — yalnızca İngilizce |
{{waitTime}} | “Number of minutes of estimated wait for a user.” |
{{waitTimeHours}} | “Math.floor(waitTime/60)” |
{{waitTimeHourMinutes}} | “waitTime%60” |
{{queueIsFull}} | “Changes to true when no more people can be added to the queue.” |
{{{turnstile}}} | “you will need to add {{{turnstile}}} somewhere in the template to let Waiting Room know where the widget should be placed” |
Etkinlik zamanlama
“When you want to customize the behavior of a waiting room for a specific period of time — such as changing the queueing method or increasing the total active users — set up a scheduled event.” “Any properties set on the event will override the default property on the waiting room for the duration of the event.”
| Alan | Kural |
|---|---|
event_start_time | event_end_time’dan en az 1 dakika önce |
prequeue_start_time | event_start_time’dan en az 5 dakika önce |
shuffle_at_event_start | true ve prequeue varsa, prequeue’daki kullanıcılar başlangıçta rastgele karıştırılıyor |
suspended | true ise etkinlik yok sayılıyor |
Override edilebilenler: new_users_per_minute, total_active_users, session_duration,
queueing_method, custom_page_html, disable_session_renewal. Bağlanma kuralı: kullanıcı
eşiklerinden birini ayarlarsan diğerini de ayarlaman gerekiyor.
“You have a limit of five events per waiting room.”
“If you need to create overlapping events, use different waiting rooms.”
Piyango deseni: prequeue_start_time + shuffle_at_event_start: true. Birebir: “Users who reach
your application during the prequeue period are randomly assigned a place in line when the event
starts.”
Bakım penceresi deseni: oda passthrough, etkinlik reject.
Bypass rules
“A Waiting Room Bypass Rule is a type of Waiting Room Rule built on Cloudflare’s Ruleset Engine.”
Kullanılamayan alanlar: cf.threat_score, cf.bot_management ile başlayanlar ve HTTP response
alanları.
Çerez davranışı
Çerez şifreli: “The __cfwaitingroom cookie is encrypted to prevent modification by users.”
Hiçbir resmî kaynak JWT demiyor; JWT olduğunu iddia eden metinler doğrulanmamıştır.
İçeriği (blog örneği):
{
"bucketId": "Mon, 11 Sep 2023 11:45:00 GMT",
"lastCheckInTime": "Mon, 11 Sep 2023 11:45:54 GMT",
"acceptedAt": "Mon, 11 Sep 2023 11:45:54 GMT"
}
Ömrü:
“While a visitor stays in a waiting room,
__cfwaitingroomcookie expiration is always set to five minutes, but renews every 20 seconds automatically as long as the visitor does not close the tab or leaves your application.”
“When the visitor accesses the application, the
__cfwaitingroomcookie expires after an interval (specified bysession_duration).”
Oturum yenileme kuralı:
“Once on your site, a user is considered active as long as they make an HTTP request to any URL covered by your waiting room once every session duration minutes.”
“Once a user has been active on your site for session duration minutes, if there is active queueing, that user will be sent to the back of the queue.”
cookie_attributes iki alan alıyor: samesite (auto | lax | none | strict) ve secure
(auto | always | never). auto, Always Use HTTPS ayarına bakarak karar veriyor.
JSON response modu — SPA ve mobil için
Örnek yanıt:
{
"cfWaitingRoom": {
"inWaitingRoom": true, "waitTimeKnown": true, "waitTime": 10,
"waitTime25Percentile": 0, "waitTime50Percentile": 0, "waitTime75Percentile": 0,
"waitTimeFormatted": "10 minutes", "queueIsFull": false, "queueAll": false,
"lastUpdated": "2020-08-03T23:46:00.000Z", "refreshIntervalSeconds": 20,
"queueingMethod": "fifo", "isFIFOQueue": true, "isRandomQueue": false,
"isPassthroughQueue": false, "isRejectQueue": false, "isEventActive": false,
"isEventPrequeueing": false, "timeUntilEventStart": 0,
"timeUntilEventStartFormatted": "unavailable", "timeUntilEventEnd": 0,
"timeUntilEventEndFormatted": "unavailable", "shuffleAtEventStart": false
}
}
İki davranış notu: waitTimeKnown false ise waitTimeFormatted "unavailable" oluyor; ve
queueingMethod reject ise refreshIntervalSeconds her zaman 0.
Çerez zorunluluğu, birebir:
“For each request to an endpoint protected by Waiting Room, the application must include the up-to-date cookie retrieved during the previous request. This is mandatory regardless of a user having been queued or not. If a request does not include a cookie, the waiting room will assume this is a new user… Consequently, this will place the user at the end of the queue.”
Turnstile uyumsuzluğu:
“Turnstile is not supported for Waiting Room JSON responses… If your application relies on JSON responses (for example, mobile apps, APIs, or other non-browser traffic), Turnstile will be disabled and cannot be enabled for these requests.”
Plan kapısı: “Only Advanced Waiting Room customers can support JSON-friendly format.”
İzleme
Saklama: “Data is stored for the past 30 days.” Minimum aralık 30 dakika.
GraphQL veri kümeleri: waitingRoomAnalyticsAdaptive ve waitingRoomAnalyticsAdaptiveGroups.
Alanlar arasında totalActiveUsers, newUsersPerMinutes, timeOnOriginP50, totalTimeWaitedP90 ve
sessionsRevoked var; boyutlar datetimeFifteenMinutes ve datetimeHour.
Status ucu:
GET zones/{zone_id}/waiting_rooms/{id}/status
“Returns queueing if the queue is activated… Returns not_queueing if the queue is not activated or if the waiting room is suspended.”
Panel durumları: Not queueing · Queueing · Disabled (askıya alınmış) · Queue-all.
Bekleme süresi çok yüksekse resmî ayar önerileri: total_active_users artır · new_users_per_minute
artır · session_duration azalt · oturum yenilemeyi kapat.
Ne zaman kullanılır, ne zaman kullanılmaz
Kullanılır
- Bilet, sınırlı stok, kampanya lansmanı gibi bilinen bir ana yığılan meşru talep varsa.
- Origin kapasiten sabit ve büyütmesi pahalıysa — kuyruk, ölçeklemeden ucuz.
- Kullanıcıya hata sayfası yerine sıra numarası göstermek istiyorsan. Ürünün asıl değeri bu.
Kullanılmaz
Bot veya DDoS problemin varsa. Doküman birebir: “Waiting Room is designed to handle legitimate traffic. If you notice frequent or abnormal queueing behavior, ensure that you are properly handling malicious and automated traffic using Cloudflare security products.” Botlar çerez taşımadığı için her istekte yeni kullanıcı sayılıyor ve slotları israf ediyor. Önce Bot Management ve WAF, sonra Waiting Room.
Rate Limiting yeterliyse. Waiting Room bir kapasite yönetimi aracı, bir kötüye kullanım aracı değil. Tek bir istemcinin API’ni dövmesini engellemek istiyorsan cevap Rate Limiting: daha ucuz, daha hassas, Business planı gerektirmiyor. Waiting Room ise tüm meşru kullanıcıları sıraya sokar.
Minimum eşikler senin için çok yüksekse. total_active_users ve new_users_per_minute minimum
200. Aynı anda 50 kullanıcı kaldıran bir origin için Waiting Room’u anlamlı bir eşiğe
ayarlayamazsın.
Kendi kuyruğunu yazmak daha doğruysa. Şu dört durumda:
- İş mantığına bağlı sıra gerekiyorsa (öncelikli müşteri, bilet tipi, üyelik seviyesi). Waiting Room FIFO ve Random dışında sıralama bilmiyor.
- Kuyruk durumunu backend’inde görmen gerekiyorsa — kim sırada, hangi ürün için.
- Kuyruktan çıkışı bir stok veya rezervasyon işlemine bağlaman gerekiyorsa.
- Bu senaryolarda Durable Objects + Workers ile kendi kuyruğunu yazmak daha doğru — Cloudflare’ın kendi ürünü de tam olarak bunun üzerine kurulu.
Path’in alt yollarla karışıyorsa. Birebir: “Waiting rooms are enabled on all subpaths, meaning
you might be sending more traffic to your waiting room than anticipated.” /shop yazarsan
/shop/api/cart de kuyruğa girer.
SEO kritikse ve crawler bypass’ı kabul edilemezse. Doğrulanmış crawler’lar kuyruğu tamamen atlıyor.
Business planındaysan ve gelişmiş özelliklere ihtiyacın varsa. Business’ta yalnızca 1 oda, yalnızca FIFO; özel şablon yok, etkinlik yok, JSON yok, bypass rule yok. Bu liste ciddi kullanım senaryolarının çoğunu Enterprise + Advanced’e taşıyor.
Ziyaretçilerin çerezleri kapatıyorsa. Ön koşul: “Visitors must enable cookies.”
Somut örnekler
Bilet satışı — piyango mantığıyla
# Oda
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms" \
--request POST --header "Authorization: Bearer $CF_API_TOKEN" \
--json '{
"name":"bilet_satisi","description":"Konser bileti",
"host":"bilet.ornek.com.tr","path":"/satis",
"total_active_users":5000,"new_users_per_minute":2000,
"session_duration":5,"queueing_method":"fifo",
"queueing_status_code":202,
"default_template_language":"tr-TR",
"cookie_attributes":{"samesite":"auto","secure":"auto"}
}'
# Etkinlik: 10 dk önce prequeue, başlangıçta karıştır
curl ".../waiting_rooms/$ROOM_ID/events" --request POST -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{
"name":"kapi_acilis",
"prequeue_start_time":"2026-09-15T16:50:00Z",
"event_start_time":"2026-09-15T17:00:00Z",
"event_end_time":"2026-09-15T19:00:00Z",
"shuffle_at_event_start":true,
"queueing_method":"random",
"total_active_users":8000,
"new_users_per_minute":3000
}'
Prequeue penceresinde gelen herkes eşit şansla sıralanıyor — “sunucuya ilk vuran kazanır” yarışını ortadan kaldıran desen bu.
SPA istemcisi
async function kuyrugaBak(url) {
const r = await fetch(url, {
headers: { 'Accept': 'application/json' }, // TAM OLARAK bu, ek değer yok
credentials: 'include' // __cfwaitingroom çerezi şart
});
if (r.status === 202) {
const { cfWaitingRoom: q } = await r.json();
const saat = Math.floor(q.waitTime / 60), dk = q.waitTime % 60;
goster(q.waitTimeKnown
? `Sıradasınız. Tahmini bekleme: ${saat} sa ${dk} dk`
: `Sıradasınız. Bekleme süresi şu anda hesaplanamıyor.`);
setTimeout(() => kuyrugaBak(url), q.refreshIntervalSeconds * 1000);
} else {
uygulamayaGir();
}
}
queueing_status_code: 202 seçmek burada kritik: 200’de bırakırsan kuyruk yanıtını gerçek yanıttan
status koduyla ayırt edemezsin.
Statik varlıkları ve sağlık ucunu bypass etmek
curl ".../waiting_rooms/$ROOM_ID/rules" --request POST -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{
"description":"statik varliklar ve health",
"expression":"ends_with(http.request.uri.path, \".js\") or ends_with(http.request.uri.path, \".css\") or ends_with(http.request.uri.path, \".woff2\") or http.request.uri.path eq \"/healthz\" or ip.src in $ofis_ip_listesi",
"action":"bypass_waiting_room"
}'
Türkçe özel şablon (Advanced)
<h1>Sıradasınız</h1>
{{#waitTimeKnown}}
<p>Tahmini bekleme: {{waitTimeHours}} saat {{waitTimeHourMinutes}} dakika</p>
{{/waitTimeKnown}}
{{^waitTimeKnown}}
<p>Tahmini bekleme süresi şu anda hesaplanamıyor.</p>
{{/waitTimeKnown}}
{{#queueIsFull}}<p>Kuyruk şu anda dolu.</p>{{/queueIsFull}}
{{{turnstile}}}
{{waitTimeFormatted}} kasten kullanılmadı — o değişken yalnızca İngilizce üretiyor.
Terraform (provider 5.24.0)
resource "cloudflare_waiting_room" "bilet" {
zone_id = var.zone_id
host = "bilet.ornek.com.tr"
name = "bilet_satisi"
path = "/satis"
total_active_users = 5000
new_users_per_minute = 2000
session_duration = 5
queueing_method = "fifo"
queueing_status_code = 202
json_response_enabled = true
default_template_language = "tr-TR"
cookie_attributes = { samesite = "auto", secure = "auto" }
cookie_suffix = "bilet"
additional_routes = [{ host = "m.ornek.com.tr", path = "/satis" }]
enabled_origin_commands = ["revoke"]
turnstile_mode = "invisible"
turnstile_action = "log"
}
Demo 1: queue_all ile yük üretmeden kuyruğu kanıtlamak
Bu demo önce yapılmalı: deterministik, tekrarlanabilir ve gerçek yük gerektirmiyor. Demo 2 zamana ve rastlantıya bağlı; bu değil.
Adım 1 — Herkesi kuyruğa al
curl -sS ".../zones/$ZONE_ID/waiting_rooms/$ROOM" --request PATCH \
-H "Authorization: Bearer $CF_API_TOKEN" --json '{"queue_all":true}'
curl -sS -o q.html -D - https://demo.ornek.com.tr/wr-test/ | head -1
# → HTTP/2 202 (tek istekte, yük üretmeden)
“If
queue_allistrue, all the traffic that is coming to a route will be sent to the waiting room. No new traffic can get to the route once this field is set and estimated time will become unavailable.”
Adım 2 — Accept başlığının tam eşleşmesini üç kontrollü deneyle kanıtla
# (a) DOĞRU başlık → JSON
curl -sS -H 'Accept: application/json' https://demo.ornek.com.tr/wr-test/ | jq .
# (b) EK DEĞERLİ başlık → HTML (dokümanın uyardığı tuzak)
curl -sS -H 'Accept: application/json, text/html' https://demo.ornek.com.tr/wr-test/ | head -3
# (c) Tarayıcı varsayılanı → HTML
curl -sS -H 'Accept: text/html,application/xhtml+xml' https://demo.ornek.com.tr/wr-test/ | head -3
Adım 3 — queue_all altındaki JSON’u oku
curl -sS -H 'Accept: application/json' https://demo.ornek.com.tr/wr-test/ \
| jq '.cfWaitingRoom | {inWaitingRoom, queueAll, waitTimeKnown, waitTimeFormatted,
queueingMethod, refreshIntervalSeconds, queueIsFull}'
Beklenen:
{
"inWaitingRoom": true,
"queueAll": true,
"waitTimeKnown": false,
"waitTimeFormatted": "unavailable",
"queueingMethod": "fifo",
"refreshIntervalSeconds": 20,
"queueIsFull": false
}
waitTimeKnown: false + waitTimeFormatted: "unavailable" — bu ikili queue_all’ın imzası.
Adım 4 — Çerez taşıyan gerçek istemci döngüsü
rm -f spa.jar
while :; do
govde=$(curl -sS -c spa.jar -b spa.jar -H 'Accept: application/json' \
-w '\n%{http_code}' https://demo.ornek.com.tr/wr-test/)
kod=$(printf '%s' "$govde" | tail -1)
json=$(printf '%s' "$govde" | sed '$d')
if [ "$kod" = "200" ]; then echo "$(date -u +%H:%M:%S) GİRİŞ AÇILDI"; break; fi
echo "$(date -u +%H:%M:%S) $kod $(printf '%s' "$json" | jq -c '.cfWaitingRoom | {waitTime, waitTimeKnown, lastUpdated}')"
sleep "$(printf '%s' "$json" | jq -r '.cfWaitingRoom.refreshIntervalSeconds')"
done
cat spa.jar ile __cfwaitingroom satırını göster — çerezin gerçekten taşındığının kanıtı.
Adım 5 — Çerezsiz kontrol grubu
Aynı döngüyü -c/-b olmadan çalıştır: lastUpdated her seferinde sıfırlanıyor, waitTime düşmüyor.
“Çerezi taşımazsan sıranın sonuna düşersin” kuralının deneysel kanıtı bu.
Adım 6 — Turnstile’ın JSON’da devre dışı olduğunu göster
curl -sS ".../waiting_rooms/$ROOM" --request PATCH -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{"turnstile_mode":"visible_managed"}'
# HTML yanıtı: widget gelir
curl -sS https://demo.ornek.com.tr/wr-test/ | grep -io 'turnstile\|challenges.cloudflare.com' | head
# JSON yanıtı: turnstile alanı boş
curl -sS -H 'Accept: application/json' https://demo.ornek.com.tr/wr-test/ | jq '.cfWaitingRoom.turnstile'
Adım 7 — reject modunda refreshIntervalSeconds sıfırlanıyor
curl -sS ".../waiting_rooms/$ROOM" --request PATCH -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{"queue_all":false,"queueing_method":"reject"}'
curl -sS -H 'Accept: application/json' https://demo.ornek.com.tr/wr-test/ \
| jq '.cfWaitingRoom | {isRejectQueue, refreshIntervalSeconds}'
# → {"isRejectQueue": true, "refreshIntervalSeconds": 0}
Tek bir jq çıktısıyla reject’in belgelenmiş davranışını kanıtlamış oluyorsun.
Bu demoda ölçülenler:
| Ölçüt | Nasıl | queue_all:false | queue_all:true | reject |
|---|---|---|---|---|
| HTTP kodu | -w '%{http_code}' | 200 | 202 | 202 |
inWaitingRoom | jq | (yanıt yok) | true | true |
waitTimeKnown | jq | true | false | false |
waitTimeFormatted | jq | “5 minutes” | "unavailable" | "unavailable" |
refreshIntervalSeconds | jq | 20 | 20 | 0 |
turnstile (JSON) | jq | boş | boş | boş |
| Turnstile (HTML) | grep | widget var | widget var | widget var |
| Status API | /status | not_queueing | queueing | queueing |
| Panel durumu | UI | Not queueing | Queue-all | Queueing |
Demo 2: Gerçek yükle eşiği aşıp kuyruğu tetiklemek
Ön koşul aritmetiği
Minimum eşikler 200. Yani kuyruğu tetiklemek için dakikada 200’den fazla yeni oturum üretmen
gerekiyor. “Yeni oturum” = __cfwaitingroom çerezi taşımayan istek. curl varsayılan olarak çerez
taşımıyor — bu işimize yarıyor.
Adım 1 — Odayı en agresif ayarlarla kur
ROOM=$(curl -sS "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms" \
--request POST -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{
"name":"demo_odasi","host":"demo.ornek.com.tr","path":"/wr-test",
"total_active_users":200,
"new_users_per_minute":200,
"session_duration":1,
"queueing_method":"fifo",
"queueing_status_code":202,
"default_template_language":"tr-TR"
}' | jq -r '.result.id')
session_duration: 1 (minimum) seç: kullanıcılar bir dakikada aktif olmaktan çıkıyor, kuyruk daha
çabuk boşalıyor, demo tekrarlanabilir oluyor.
Adım 2 — İki ön koşulu doğrula
DNS kaydı. demo.ornek.com.tr için proxied (turuncu bulut) bir kayıt olmalı — oda
oluşturulunca otomatik gelmiyor.
Rate limiting. Doküman birebir: “Reviewed your rate limiting rules to make sure they allow at least one request every 20 seconds (required for automatic page refreshes).” Aksi halde yük üreticini kendi WAF’ın bloklar ve “kuyruk çalışmıyor” sanırsın.
Adım 3 — Başlangıç ölçümü ve status izleme
curl -sS "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$ROOM/status" \
-H "Authorization: Bearer $CF_API_TOKEN" | jq -r '.result.status'
# → not_queueing
# ayrı terminal
while true; do
printf '%s ' "$(date -u +%H:%M:%S)"
curl -sS ".../waiting_rooms/$ROOM/status" -H "Authorization: Bearer $CF_API_TOKEN" \
| jq -r '.result.status'
sleep 10
done | tee wr-status.log
Adım 4 — Yükü sür
# 3 dakika boyunca yaklaşık 600 yeni oturum/dakika
bitis=$(( $(date +%s) + 180 ))
while [ $(date +%s) -lt $bitis ]; do
seq 1 100 | xargs -P 40 -I{} curl -sS -o /dev/null \
-w '%{http_code}\n' https://demo.ornek.com.tr/wr-test/
sleep 5
done | sort | uniq -c
Doküman: “run your test script or planner for a period of time longer than a minute, ideally more than 2-3 minutes.”
Adım 5 — Türkçe kuyruk sayfasını yakala
curl -sS -D headers.txt -o queue.html https://demo.ornek.com.tr/wr-test/
head -1 headers.txt # HTTP/2 202
grep -i 'set-cookie' headers.txt # __cfwaitingroom=...
Türkçe bir portal için gösterilmeye değer tek ekran bu: tek satır ayarla gelen resmî Türkçe sayfa.
Adım 6 — Sırada ilerlemeyi göster
rm -f wrjar.txt
for i in $(seq 1 15); do
kod=$(curl -sS -c wrjar.txt -b wrjar.txt -o sayfa.html -w '%{http_code}' \
https://demo.ornek.com.tr/wr-test/)
echo "$(date -u +%H:%M:%S) $kod $(grep -o -E '[0-9]+ (dakika|minute)' sayfa.html | head -1)"
sleep 20
done
Adım 7 — Panel doğrulaması
Adım 8 — Temizlik
curl -sS ".../waiting_rooms/$ROOM" --request PATCH -H "Authorization: Bearer $CF_API_TOKEN" \
--json '{"queue_all":false,"queueing_method":"fifo","suspended":true}'
Askıya alındığında: “traffic goes to the origin and the __cfwaitingroom cookie is not created.”
Bu demoda ölçülenler:
| Ölçüt | Nasıl | Yükten önce | Yük altında |
|---|---|---|---|
| Status API | /status ucu | not_queueing | queueing |
| HTTP kodu dağılımı | xargs döngüsü | %100 200 | 202 payı > 0 |
Set-Cookie: __cfwaitingroom | -D headers.txt | yok veya geçici | her yeni oturumda |
| Sayfa içeriği | queue.html | uygulama HTML’i | Türkçe kuyruk şablonu |
| Tahmini bekleme | sayfadaki sayaç | — | dakika cinsinden |
| Panelde “Queued users” | Analytics | 0 | > 0 |
| Status gecikmesi | log zaman damgaları | — | 20–50 sn (resmî) |
Fiyatlandırma
Plan tablosu
“The features available for a waiting room depend on your plan type. You can only have one plan per zone. One basic waiting room is included in all Business and Enterprise plans. On an Enterprise plan, you can purchase advanced waiting room(s) to unlock all of the additional advanced features.”
| Free | Pro | Business | Enterprise | |
|---|---|---|---|---|
| Kullanılabilirlik | ✘ | ✘ | ✅ | ✅ |
| Oda sayısı | 0 | 0 | 1 | 1 varsayılan; Advanced ile daha fazlası satın alınabilir |
| Özel şablon | ✘ | ✘ | ✘ | Advanced |
| Queueing method’lar | ✘ | ✘ | yalnızca FIFO | FIFO varsayılan; Advanced ile dördü |
| Çoklu hostname ve path | ✘ | ✘ | ✘ | Advanced |
| Oturum yenilemeyi kapatma | ✘ | ✘ | ✘ | Advanced |
| JSON yanıt | ✘ | ✘ | ✘ | Advanced |
| Queueing status code | ✘ | ✘ | ✅ | ✅ |
| Zamanlanmış etkinlik | ✘ | ✘ | ✘ | Advanced |
| Bypass rules | ✘ | ✘ | ✘ | Advanced |
| Session Revocation | ✘ | ✘ | ✘ | Advanced |
| SEO Crawler Bypassing | ✘ | ✘ | ✅ | ✅ |
| Turnstile widget modu | ✘ | ✘ | yalnızca invisible | Advanced ile üç mod |
| Turnstile fail action | ✘ | ✘ | yalnızca log | Advanced ile infinite queue |
Sayısal limitler
| Limit | Değer |
|---|---|
total_active_users | min 200, maks 2.147.483.647 |
new_users_per_minute | min 200, ≤ total_active_users |
session_duration | 1–30 dakika, varsayılan 5 |
| Özel HTML şablonu | 1.048.576 bayt (1 MB) |
| Etkinlik sayısı | oda başına 5 |
| Zone başına oda | Business 1; Enterprise 1 varsayılan + satın alınabilir |
queueing_status_code | 200 / 202 / 429 |
cookie_suffix | maks 32 karakter |
| Analitik saklama | 30 gün, min aralık 30 dakika |
prequeue_start_time | başlangıçtan en az 5 dk önce |
event_start_time | bitişten en az 1 dk önce |
additional_routes sayısı | belgelenmemiş |
| Bypass rule sayısı | belgelenmemiş |
Not: güncel dokümantasyonda /waiting-room/reference/limits/ diye bir sayfa yok — limitler plans
tablosuna, API şemasına ve özellik sayfalarına dağılmış.
Ücret
| Kalem | Durum |
|---|---|
| Plan tabanı | Business ve üzeri; Free ve Pro’da yok |
| Business planı | “$200/mo billed annually, or $250/mo billed monthly” |
| Business’a dahil | “One basic waiting room is included in all Business and Enterprise plans.” |
| Advanced Waiting Room | Enterprise eklentisi; cloudflare.com/plans/enterprise/ sayfasında kalem olarak listeleniyor |
| Enterprise önizleme | “non-contract service, which provides full access, free of metered usage fees, limits…” |
| Ücretsiz erişim yolu | Project Fair Shot (cloudflare.com/fair-shot/) kapsamındakiler |
Dürüst özet
Waiting Room Business planına dahil (yıllık ödemede $200/ay, aylıkta $250/ay) — ama Business’ta yalnızca 1 oda ve yalnızca FIFO; özel şablon, etkinlik, JSON ve bypass rule yok. Gerçek üretim senaryolarının çoğu Enterprise + Advanced Waiting Room eklentisi gerektiriyor ve bu eklentinin fiyatı Cloudflare tarafından yayımlanmıyor. Kullanıcı veya kuyruk başına metered ücret yok.
Lisanslama ve hukuki çerçeve
Hizmet tescillidir ve Cloudflare Hizmet Şartları’na tabidir.
__cfwaitingroom çerezi ve KVKK. Teknik olarak zorunlu bir sıra ve oturum çerezidir: şifrelidir,
kullanıcı profili veya takip kimliği taşımaz, tek işi sıradaki yerini ve uygulamada geçirdiğin süreyi
izlemektir. Çerez politikanda zorunlu çerezler altında listelemen ve amacını belirtmen yeterli.
Cloudflare bu çerez için Türkiye’ye özgü hiçbir metin yayımlamamıştır.
Ziyaretçi bilgilendirmesi. Kuyruğa alınan kullanıcı bir sıra numarası ve tahmini süre görüyor; bunun ötesinde kişisel veri işlenmiyor. Özel şablon kullanıyorsan, şablona kendi ekleyeceğin analitik veya izleme kodları ayrı bir değerlendirme konusu — Cloudflare’ın varsayılan sayfası böyle bir kod içermiyor.
İşlem sırası. Waiting Room’dan önce çalışanlar: DDoS Mitigation, WAF, Bot Management ve Page Rules. Waiting Room’dan sonra çalışan: Workers. Yani bir Worker’ın Waiting Room kararını değiştirmesi mümkün değil, ama WAF kuralın kuyruğa girmeden trafiği kesebilir.
Sık yapılan hatalar
DNS kaydını unutmak. Birebir: “A DNS record is not auto-configured after a waiting room is created.” Kayıt proxied olmalı.
Path’i yanlış harflerle yazmak. Büyük/küçük harfe duyarlı; wildcard ve query parametresi desteklenmiyor.
Alt yolları hesaba katmamak. “Waiting rooms are enabled on all subpaths.” /shop yazarsan
/shop/api/cart de kuyruğa girer.
Şablon varlıklarını korunan hostname’de barındırmak. CSS, JS ve görsel istekleri kuyruğa takılıyor ve sayfa çıplak görünüyor.
Rate limiting kuralının 20 saniyelik yenilemeyi bloklaması. “make sure they allow at least one request every 20 seconds.”
Accept: application/json, text/html göndermek. Tam eşleşme şart; JSON dönmüyor.
Mobil istemcide çerezi taşımamak. Her istek yeni kullanıcı sayılıyor, kullanıcı asla öne gelmiyor.
additional_routes kullanıp cookie_suffix vermemek. Doküman bu durumda cookie_suffix’i
zorunlu sayıyor.
Bypass rule’ları cömertçe yazmak. Bypass edilen trafik aktif kullanıcı olarak sayılmıyor ve queue-all, reject, prequeue hiçbiri uygulanmıyor.
Alt-istekleri bypass listesine almayı unutmak. “make sure to include in your expression any paths or file types that subrequests may be hitting.”
Kuyruk aktifken ayarları oynamak. “only make changes to your configuration settings when necessary. These changes may impact the estimated wait time shown to end users.” (Şablon değişiklikleri güvenli: “All changes will be visible to your users in close to real time.”)
Testi bir dakikadan kısa sürdürmek. “run your test script or planner for a period of time longer than a minute, ideally more than 2-3 minutes.”
queueing_status_code’u 200’de bırakıp sonra kuyruğu tespit edememek. 202 veya 429 seç — hem demo
hem üretim izlemesi için.
Waiting Room’u bot veya DDoS savunması sanmak. “Waiting Room is designed to handle legitimate traffic.”
Çakışan etkinlik yaratmaya çalışmak. “If you need to create overlapping events, use different waiting rooms.” Ve oda başına en fazla 5 etkinlik.
Sıkça sorulan sorular
- Bekleme odası sayfasını Türkçe gösterebilir miyim?
- Evet, tek satırla:
default_template_language: "tr-TR". Türkçe, Cloudflare'ın varsayılan sayfa dilleri arasında birebir listeleniyor ve API enum'undatr-TRvar. Tam kontrol için özel şablon gerekiyor, o da Advanced eklentisi istiyor. - Özel şablonda “5 dakika” yazısını Türkçe yapabilir miyim?
{{waitTimeFormatted}}ile hayır — doküman birebir: “the following variables are only available in English:waitTimeFormatted,timeUntilEventStartFormatted, andtimeUntilEventEndFormatted.” Kendin kur:{{waitTimeHours}} saat {{waitTimeHourMinutes}} dakika.- Business planındayım, etkinlik zamanlaması yapabilir miyim?
- Hayır. Scheduled events, özel şablon, JSON yanıt, bypass rules ve FIFO dışı queueing method'ların hepsi Enterprise + Advanced istiyor. Business'ta yalnızca 1 oda ve yalnızca FIFO var. Bu liste ciddi kullanım senaryolarının çoğunu Enterprise'a taşıyor.
- Minimum 200 aktif kullanıcı sınırı benim için çok yüksek.
- Bu bir ürün sınırı, aşılamıyor:
total_active_usersvenew_users_per_minuteminimum 200. Origin'in aynı anda 200'den az kullanıcı kaldırıyorsa Waiting Room'u anlamlı bir eşiğe ayarlayamazsın. Küçük siteler için ürün uygun değil. - Rate Limiting ile farkı ne?
- Rate Limiting kötüye kullanımı engeller (IP veya token başına istek hızı). Waiting Room meşru kapasite fazlasını sıraya alır ve kullanıcıya sıra artı tahmini süre verir. Bilet satışında ikisine de ihtiyacın olur: botları Rate Limiting ve Bot Management ayıklar, kalan gerçek talebi Waiting Room sıraya alır.
- Kendi kuyruğumu Workers + Durable Objects ile yazsam?
- Cloudflare'ın Waiting Room'u da tam olarak bunun üzerine kurulu. Kendin yaz eğer: iş mantığına bağlı sıralama gerekiyorsa (öncelikli müşteri, bilet tipi), kuyruk durumunu backend'inde görmen gerekiyorsa, veya kuyruktan çıkışı bir stok/rezervasyon işlemine bağlaman gerekiyorsa. Waiting Room FIFO ve Random dışında sıralama bilmiyor. Aksi halde hazır ürün daha güvenilir.
- Path'im <code>/Kara-Cuma</code>, kullanıcılar <code>/kara-cuma</code> yazıyor — neden kuyruğa girmiyorlar?
- Path büyük/küçük harfe duyarlı. Resmî SSS birebir: “if you have a waiting room set up for
/Black-Friday-Saleand users go to/black-friday-sale, they will bypass your waiting room.” Wildcard ve query parametresi de desteklenmiyor. - Kullanıcı sekmeyi yenilerse sırasını kaybeder mi?
- Hayır. Birebir: “A manual tab refresh has no effect on a user's position… However, if they close their tab and then try to access the application again during active queueing, they will lose their spot.” Kuyrukta beklerken çerezin ömrü hep beş dakika ama 20 saniyede bir otomatik yenileniyor.
- Ayarladığım “new users per minute” eşiği neden aşıldı?
- Tasarım gereği. Resmî SSS birebir: “In the case of a rapid spike — rising to several thousand users within a minute — the global state propagation process takes approximately two minutes, resulting in a delay before all data centers become aware of the spike.” Hata değil, dağıtık mimarinin bedeli.
- Mobil uygulamamda kuyruk çalışmıyor.
- Üç klasik sebep. (a)
Acceptbaşlığın tam olarakapplication/jsondeğil —application/json, text/htmlbile HTML döndürüyor. (b)__cfwaitingroomçerezini isteklerde taşımıyorsun; her istekte sıranın sonuna düşüyorsun. (c) JSON modu Advanced istiyor. - <code>__cfwaitingroom</code> çerezi KVKK açısından sorun mu?
- Teknik olarak zorunlu bir sıra/oturum çerezi: şifreli (“encrypted to prevent modification by users”), kullanıcı profili taşımıyor, tek işi sıradaki yerini ve uygulamada geçirdiğin süreyi izlemek. Çerez politikanda zorunlu çerezler altında listele. Cloudflare'ın Türkiye'ye özel resmî bir metni yok.
- SEO'm etkilenir mi?
- SEO Crawler Bypassing Business ve Enterprise'da var. Ama uyarı birebir: “By enabling this service, you understand that these verified crawlers are completely bypassing your waiting rooms.” Yani doğrulanmış crawler doğrudan origin'ine gidiyor — kuyruğun onu korumuyor.
- Bot trafiği kuyruğumu neden tıkıyor?
- Birebir: “Since bots usually do not persist cookies from one request to the next, they end up counting as multiple inactive users in the queue and prevent full utilization of available slots.” Yani her botsuz-çerezli istek yeni bir kullanıcı sayılıyor ve slot israfı oluyor. Çözüm: Turnstile'ı aç (3 Mart 2025'ten beri tüm planlarda invisible mod var) ve önden Bot Management veya WAF ile temizle.
- Waiting Room analitiğim Google Analytics ile uyuşmuyor.
- Farklı şeyleri sayıyorlar. Waiting Room
session_durationbazlı sayıyor — bir kullanıcı, o süre içinde istek attığı sürece aktif. GA ise JavaScript tabanlı ölçüyor. Farklı tanım, farklı rakam. Resmî SSS bunu açıkça ele alıyor.
İlgili servisler
- Load BalancingTrafiği birden çok origin arasında dağıtır, health check yapar, arızalıyı devre dışı bırakır.
- Rate LimitingIP, oturum veya özel anahtara göre request sayısını sınırlar.
- TurnstileKullanıcıya bulmaca çözdürmeyen CAPTCHA alternatifi.
- Bot ManagementHer request’e bot skoru verir; kazıyıcı, kimlik doldurma ve stok kapma trafiğini ayırır.
Bu sayfadaki fiyat ve özellik bilgileri 1 Eylül 2026 tarihinde Cloudflare’in resmî kaynaklarından doğrulanmıştır. Cloudflare fiyatlandırmasını önceden haber vermeden değiştirebilir; bağlayıcı bilgi içinresmî sayfaya bakın.