İçeriğe atla
Cloudflare Wiki

    gez · aç · Esc kapat

    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 __cfwaitingroom cookie. 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

    PanelAPI alanıZorunluSınır / varsayılan
    NamenameEvetalfanümerik, tire ve alt çizgi
    HostnamehostEvetwildcard yok, https:// yazma
    PathpathHayırbüyük/küçük harfe duyarlı, wildcard ve query yok
    Additional Hostnames and Pathsadditional_routesHayırAdvanced; sonda örtük wildcard var
    Custom Cookie Suffixcookie_suffixadditional_routes varsa evetmaks 32 karakter
    Total active userstotal_active_usersEvetmin 200, maks 2147483647
    New users per minutenew_users_per_minuteEvetmin 200, ≤ total_active_users
    Session durationsession_durationHayır1–30 dakika, varsayılan 5
    Disable session renewaldisable_session_renewalHayırEnterprise + satın alma
    JSON responsejson_response_enabledHayırAdvanced; varsayılan false
    Queueing status codequeueing_status_codeHayırenum 200 / 202 / 429, varsayılan 200
    Session Revocationenabled_origin_commandsHayır["revoke"], Advanced
    Turnstile Widget Modeturnstile_modeEvetoff · invisible · visible_non_interactive · visible_managed
    Turnstile Fail Actionturnstile_actionEvetlog · infinite_queue
    Queue allqueue_allHayırvarsayılan false
    Queueing methodqueueing_methodHayırvarsayılan fifo
    SuspendedsuspendedHayırtrue ise trafik kuyruğa girmiyor
    Custom HTMLcustom_page_htmlHayırAdvanced, maks 1 MB
    Varsayılan dildefault_template_languageHayır37 locale, tr-TR dahil; yoksa en-US

    Queueing method’lar

    MethodBirebir tanımNe 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şkenBirebir 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.”

    AlanKural
    event_start_timeevent_end_time’dan en az 1 dakika önce
    prequeue_start_timeevent_start_time’dan en az 5 dakika önce
    shuffle_at_event_starttrue ve prequeue varsa, prequeue’daki kullanıcılar başlangıçta rastgele karıştırılıyor
    suspendedtrue 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, __cfwaitingroom cookie 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 __cfwaitingroom cookie expires after an interval (specified by session_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_all is true, 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.”

    HTTP 202 yanıt başlığı ve bekleme süresi göstermeyen kuyruk sayfası
    Traffic → Waiting Room kartında durumun Queue-all olarak görünmesi

    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
    Yalnızca (a) şıkkının JSON döndürdüğünü, (b) ve (c)'nin HTML döndürdüğünü gösteren yan yana çıktı

    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
    }
    jq çıktısında waitTimeKnown false ve waitTimeFormatted unavailable değerleri

    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ı.

    Zaman damgalı satırlar; waitTime azalırken lastUpdated ilerliyor ve sonunda GİRİŞ AÇILDI
    cat spa.jar çıktısında __cfwaitingroom satırı

    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.

    lastUpdated'ın her istekte sıfırlandığını ve waitTime'ın düşmediğini gösteren çıktı

    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'
    HTML'de challenges.cloudflare.com eşleşmesi, aynı anda JSON'da boş turnstile alanı

    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}
    isRejectQueue true ve refreshIntervalSeconds 0 değerleri

    Tek bir jq çıktısıyla reject’in belgelenmiş davranışını kanıtlamış oluyorsun.

    Bu demoda ölçülenler:

    ÖlçütNasılqueue_all:falsequeue_all:truereject
    HTTP kodu-w '%{http_code}'200202202
    inWaitingRoomjq(yanıt yok)truetrue
    waitTimeKnownjqtruefalsefalse
    waitTimeFormattedjq“5 minutes”"unavailable""unavailable"
    refreshIntervalSecondsjq20200
    turnstile (JSON)jqboşboşboş
    Turnstile (HTML)grepwidget varwidget varwidget var
    Status API/statusnot_queueingqueueingqueueing
    Panel durumuUINot queueingQueue-allQueueing

    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
    not_queueing dönen çıktı ve izleme döngüsünün ilk satırları

    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.”

    Başta yalnızca 200, sonra 202 payının belirdiği sayım çıktısı
    wr-status.log'da not_queueing'den queueing'e geçişin zaman damgası

    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=...
    default_template_language tr-TR ile gelen varsayılan kuyruk sayfasının tarayıcı görünümü

    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
    Zaman damgalı satırlarda dakika sayacının düşmesi ve kodun 202'den 200'e dönmesi

    Adım 7 — Panel doğrulaması

    Traffic → Waiting Room → Analytics'te kuyruk eğrisinin yükseldiği an
    200 eşiğinin aşıldığı noktayı gösteren grafik
    Analytics panelinde iki dağılım grafiği

    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çütNasılYükten önceYük altında
    Status API/status ucunot_queueingqueueing
    HTTP kodu dağılımıxargs döngüsü%100 200202 payı > 0
    Set-Cookie: __cfwaitingroom-D headers.txtyok veya geçiciher yeni oturumda
    Sayfa içeriğiqueue.htmluygulama HTML’iTürkçe kuyruk şablonu
    Tahmini beklemesayfadaki sayaçdakika cinsinden
    Panelde “Queued users”Analytics0> 0
    Status gecikmesilog 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.”

    FreeProBusinessEnterprise
    Kullanılabilirlik
    Oda sayısı0011 varsayılan; Advanced ile daha fazlası satın alınabilir
    Özel şablonAdvanced
    Queueing method’laryalnızca FIFOFIFO varsayılan; Advanced ile dördü
    Çoklu hostname ve pathAdvanced
    Oturum yenilemeyi kapatmaAdvanced
    JSON yanıtAdvanced
    Queueing status code
    Zamanlanmış etkinlikAdvanced
    Bypass rulesAdvanced
    Session RevocationAdvanced
    SEO Crawler Bypassing
    Turnstile widget moduyalnızca invisibleAdvanced ile üç mod
    Turnstile fail actionyalnızca logAdvanced ile infinite queue

    Sayısal limitler

    LimitDeğer
    total_active_usersmin 200, maks 2.147.483.647
    new_users_per_minutemin 200, ≤ total_active_users
    session_duration1–30 dakika, varsayılan 5
    Özel HTML şablonu1.048.576 bayt (1 MB)
    Etkinlik sayısıoda başına 5
    Zone başına odaBusiness 1; Enterprise 1 varsayılan + satın alınabilir
    queueing_status_code200 / 202 / 429
    cookie_suffixmaks 32 karakter
    Analitik saklama30 gün, min aralık 30 dakika
    prequeue_start_timebaşlangıçtan en az 5 dk önce
    event_start_timebitiş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

    KalemDurum
    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 RoomEnterprise 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 yoluProject 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'unda tr-TR var. 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, and timeUntilEventEndFormatted.” 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_users ve new_users_per_minute minimum 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-Sale and 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) Accept başlığın tam olarak application/json değil — application/json, text/html bile 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_duration bazlı 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.

    Hata bildir

    Yanlış bir rakam, eskimiş bir bilgi veya bozuk bir bağlantı mı buldun? Bildir, kaynağıyla birlikte kontrol edelim.