WordPress Heartbeat API’yi Kontrol Altına Alma
WordPress siteniz yavaşlıyorsa ve sunucu kaynaklarınız gereksiz yere tükeniyorsa, suçlu çoğu zaman fark etmediğiniz bir yerden geliyor: Heartbeat API. Bu mekanizma, WordPress’in arka planda sürekli sunucunuzla “konuşmasını” sağlıyor. Peki bu konuşma ne zaman zararlı hale gelir ve nasıl kontrol altına alırsınız? Gelin, functions.php üzerinden yapabileceğiniz her şeyi adım adım inceleyelim.
WordPress Heartbeat API Nedir?
WordPress 3.6 ile hayatımıza giren Heartbeat API, tarayıcı ile sunucu arasında düzenli aralıklarla AJAX istekleri göndererek bazı özelliklerin çalışmasını sağlar. Bu özellikler şunlardır:
- Otomatik taslak kaydetme: Yazı yazarken içeriğiniz kaybolmasın diye arka planda kaydeder
- Çoklu kullanıcı kilitleme: Aynı yazıyı iki kişi düzenlemesin diye kilit mekanizması
- Oturum süresi uyarısı: “Oturumunuz sona eriyor” bildirimleri
- WooCommerce stok güncellemeleri: Gerçek zamanlı stok takibi
Teknik olarak baktığımızda, bu API /wp-admin/admin-ajax.php üzerinden POST istekleri gönderiyor. Varsayılan ayarlarda bu istek her 15 ila 60 saniyede bir tekrarlanıyor. Şimdi düşünün: Aynı anda 50 kullanıcı WordPress admin panelinde açık tutuyorsa, sunucunuz dakikada onlarca gereksiz istek işliyor demektir.
Paylaşımlı hosting kullanıyorsanız veya düşük kaynaklı bir VPS üzerindeyseniz, bu durum ciddi performans sorunlarına yol açar. WooCommerce kurulu sitelerde heartbeat aktivitesi çok daha yoğun olabiliyor.
Sorunun Gerçek Boyutu
Bir müşteri sitesinde şunu yaşadım: WooCommerce mağazası, günde 200-300 sipariş alan orta ölçekli bir site. Sunucu kaynak kullanımı sürekli yüksek, MySQL bağlantıları zaman zaman max_connections limitine dayanıyor. New Relic ile analiz yaptığımızda, gün içindeki AJAX isteklerinin yaklaşık %35’inin sadece Heartbeat kaynaklı olduğunu gördük.
Çözüm basitti: Heartbeat’i tamamen kapatmak değil, kontrollü şekilde yönetmek. İşte bu yazıda anlatacağım da tam olarak bu.
Temel Yaklaşımlar
Heartbeat API’yi yönetmek için üç farklı strateji var:
- Tamamen devre dışı bırakmak: En agresif yöntem, bazı WordPress özelliklerini kırar
- Belirli sayfalarda devre dışı bırakmak: Önerilen yaklaşım, hassas dengeyi korur
- Frekansı azaltmak: Heartbeat çalışmaya devam eder ama daha seyrek istek atar
Şimdi bu stratejilerin her birini kod örnekleriyle görelim.
functions.php’ye Ekleme Yapma Rehberi
Tüm bu kodları wp-content/themes/temaniz/functions.php dosyasına ekleyeceksiniz. Eğer child theme kullanıyorsanız (ki her zaman kullanmanızı öneririm), child theme’nin functions.php dosyasına ekleyin. Değişiklik yapmadan önce yedek almayı unutmayın.
# functions.php'yi düzenlemeden önce yedekleyin
cp /var/www/html/wp-content/themes/yourtheme/functions.php
/var/www/html/wp-content/themes/yourtheme/functions.php.bak
# Dosyayı açın
nano /var/www/html/wp-content/themes/yourtheme/functions.php
Heartbeat’i Tamamen Devre Dışı Bırakma
En basit ama en sert yöntemden başlayalım. Bunu yaparsanız otomatik taslak kaydetme ve çoklu düzenleme kilidi gibi özellikler çalışmaz.
<?php
// Heartbeat API'yi tamamen devre dışı bırak
add_action('init', function() {
wp_deregister_script('heartbeat');
}, 1);
Bu yöntem çok kaba. Sadece heartbeat’in neden olduğu sorunları test etmek için geçici olarak kullanın. Üretim ortamında bu kadar agresif olmaya gerek yok.
Sadece Ön Yüzde Devre Dışı Bırakma
Ziyaretçilerin gördüğü sayfalarda heartbeat çalışmamalı, bu kesin. Sadece admin panelinde ve yazı editöründe aktif olması yeterli.
<?php
// Sadece ön yüzde heartbeat'i kapat
add_action('init', function() {
if (!is_admin()) {
wp_deregister_script('heartbeat');
}
}, 1);
Bu kod sitenizin ön yüzünde heartbeat’i tamamen kapatırken, WordPress yönetim panelinde çalışmaya devam etmesine izin verir. Çoğu site için bu kadar bile büyük bir performans artışı sağlar. Özellikle blog ve içerik siteleri için bu ayar yeterlidir.
Sayfa Bazlı Hassas Kontrol
Daha gelişmiş bir yaklaşım: Heartbeat’i hangi admin sayfalarında çalıştırmak istediğinizi belirleyin. Yazı editörü dışındaki tüm admin sayfalarında kapatabilirsiniz.
<?php
// Heartbeat'i sadece post edit sayfasında aktif tut
add_action('init', function() {
global $pagenow;
// Ön yüzde her zaman kapat
if (!is_admin()) {
wp_deregister_script('heartbeat');
return;
}
// Admin'de sadece belirli sayfalarda aktif bırak
$allowed_pages = [
'post.php', // Yazı düzenleme
'post-new.php', // Yeni yazı oluşturma
];
if (!in_array($pagenow, $allowed_pages)) {
wp_deregister_script('heartbeat');
}
}, 1);
Bu yaklaşım çok daha akıllıca. Örneğin WooCommerce sipariş listesinde, medya kütüphanesinde, eklenti listesinde heartbeat’e gerek yok. Sadece gerçekten ihtiyaç duyulan yerlerde çalıştırın.
Heartbeat Frekansını Azaltma
Heartbeat’i kapatmak istemiyorsunuz ama daha seyrek çalıştırmak istiyorsunuz. İşte burada heartbeat_settings filtresi devreye giriyor.
<?php
// Heartbeat frekansını azalt
add_filter('heartbeat_settings', function($settings) {
// Interval değeri saniye cinsinden (min: 15, max: 120)
$settings['interval'] = 60; // Varsayılan 15-60 arası, biz 60'a çekiyoruz
return $settings;
});
Interval değeri için bilmeniz gerekenler:
- 15: Minimum değer, en sık kontrol
- 60: Varsayılan maksimum değer
- 120: Maksimum değer, en seyrek kontrol (bazı kaynaklarda 300’e kadar çıkılabileceği belirtilse de resmi destek 120’ye kadar)
Eğer WooCommerce kullanıyorsanız ve gerçek zamanlı stok takibi önemliyse, bu değeri çok yüksek tutmayın. 60 saniye genellikle iyi bir denge noktasıdır.
Kapsamlı Heartbeat Yönetim Fonksiyonu
Şimdiye kadar anlattıklarımı tek bir fonksiyonda birleştirelim. Bu, production’da kullanabileceğiniz, bakımı kolay bir yapı:
<?php
/**
* WordPress Heartbeat API Optimizasyonu
*
* Bu fonksiyon heartbeat'i sayfa bazlı yönetir:
* - Ön yüzde tamamen kapalı
* - Admin'de sadece editör sayfalarında aktif
* - Aktif olduğu yerlerde frekans azaltılmış
*/
function optimize_heartbeat_api() {
global $pagenow;
// 1. Ön yüzde tamamen kapat
if (!is_admin()) {
wp_deregister_script('heartbeat');
return;
}
// 2. Login sayfasında kapat
if (in_array($pagenow, ['wp-login.php'])) {
wp_deregister_script('heartbeat');
return;
}
// 3. Heartbeat'e ihtiyaç duymayan admin sayfaları
$disable_on_pages = [
'upload.php', // Medya kütüphanesi
'plugins.php', // Eklentiler
'themes.php', // Temalar
'users.php', // Kullanıcılar
'tools.php', // Araçlar
'options-general.php', // Genel ayarlar
'edit-comments.php', // Yorumlar
'edit.php', // Yazı/sayfa listesi (editör değil, liste)
];
if (in_array($pagenow, $disable_on_pages)) {
wp_deregister_script('heartbeat');
return;
}
// 4. Aktif kaldığı yerlerde frekansı optimize et
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = 60; // 15 yerine 60 saniye
return $settings;
});
}
add_action('init', 'optimize_heartbeat_api', 1);
Bu yapıyı birkaç farklı müşteri sitesinde uyguladık. Ortalama olarak admin-ajax.php üzerindeki yük yaklaşık %60-70 oranında azalıyor.
WooCommerce İçin Özel Ayarlar
WooCommerce mağazanız varsa biraz daha dikkatli olmanız gerekiyor. WooCommerce bazı işlemler için heartbeat’e bağımlı. Sipariş yönetimi ve stok takibi bunu kullanıyor.
<?php
/**
* WooCommerce uyumlu Heartbeat optimizasyonu
*/
function woocommerce_compatible_heartbeat() {
global $pagenow;
if (!is_admin()) {
wp_deregister_script('heartbeat');
return;
}
// WooCommerce sayfalarını tespit et
$current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
$post_type = isset($_GET['post_type']) ? sanitize_text_field($_GET['post_type']) : '';
// WooCommerce sipariş ve ürün düzenleme sayfaları
$woo_needs_heartbeat = (
$pagenow === 'post.php' ||
$pagenow === 'post-new.php' ||
($pagenow === 'edit.php' && $post_type === 'shop_order') ||
strpos($current_page, 'woocommerce') !== false
);
if (!$woo_needs_heartbeat) {
wp_deregister_script('heartbeat');
return;
}
// WooCommerce sayfalarında frekansı biraz daha agresif tut
// ama yine de varsayılandan az olsun
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = 45;
return $settings;
});
}
add_action('init', 'woocommerce_compatible_heartbeat', 1);
Kullanıcı Rolüne Göre Heartbeat Yönetimi
Bir adım daha ileri gidelim: Kimi kullanıcıların heartbeat’e gerçekten ihtiyacı var? Editörler ve yazarlar evet, ama sadece okuma yetkisi olan bir abone neden heartbeat kullansın?
<?php
/**
* Kullanici rolune gore heartbeat yonetimi
*/
function role_based_heartbeat() {
// Ön yüzde her zaman kapat
if (!is_admin()) {
wp_deregister_script('heartbeat');
return;
}
// Kullanıcı giriş yapmamışsa kapat
if (!is_user_logged_in()) {
wp_deregister_script('heartbeat');
return;
}
$current_user = wp_get_current_user();
// Heartbeat'e ihtiyaç duymayan roller
$low_priority_roles = ['subscriber', 'customer'];
// Kullanıcının rollerinden herhangi biri düşük öncelikli mi?
$user_roles = (array) $current_user->roles;
$has_low_priority_role = !empty(array_intersect($user_roles, $low_priority_roles));
if ($has_low_priority_role) {
wp_deregister_script('heartbeat');
return;
}
// Yönetici ve editörler için optimize edilmiş frekans
if (in_array('administrator', $user_roles)) {
// Admin için biraz daha sık - gerçek zamanlı takip önemli olabilir
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = 30;
return $settings;
});
} else {
// Diğer roller için daha seyrek
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = 60;
return $settings;
});
}
}
add_action('init', 'role_based_heartbeat', 1);
Etkinliği Test Etme
Değişikliklerinizin çalışıp çalışmadığını doğrulamak için birkaç yöntem:
Birinci yöntem, tarayıcı geliştirici araçlarıyla test:
- Chrome/Firefox’ta F12 tuşuna basın
- Network sekmesine gidin
- Filtre kutusuna
admin-ajaxyazın - Sayfada bekleyin ve gelen istekleri gözlemleyin
Eğer heartbeat kapatılmışsa hiç istek görmemelisiniz. Eğer sadece frekans azaltılmışsa, istekler arasındaki sürenin arttığını göreceksiniz.
İkinci yöntem, sunucu log analizi:
# Apache için admin-ajax.php isteklerini say
grep "admin-ajax.php" /var/log/apache2/access.log |
grep "heartbeat" |
wc -l
# Nginx için
grep "admin-ajax.php" /var/log/nginx/access.log |
awk '{print $1}' |
sort | uniq -c | sort -rn | head -20
# Gerçek zamanlı izleme
tail -f /var/log/nginx/access.log | grep "admin-ajax"
Üçüncü yöntem, MySQL sorgu sayısını izleme:
# MySQL slow query log'u aktif edin
mysql -u root -p -e "SET GLOBAL slow_query_log = 'ON';"
mysql -u root -p -e "SET GLOBAL long_query_time = 1;"
# Heartbeat kaynaklı sorguları izleyin
mysqladmin -u root -p processlist | grep -i "heartbeat"
Tüm Kodları Bir Arada Kullanma
Yukarıda anlattığım tüm yaklaşımları gerçek dünya için birleştirdiğimde ortaya şu çıkıyor:
<?php
/**
* Heartbeat API Master Controller
*
* Kurulum: functions.php dosyasına ekleyin
* Uyumluluk: WordPress 5.0+, WooCommerce 5.0+
*/
// Konfigürasyon - ihtiyacınıza gore degistirin
define('HEARTBEAT_FRONTEND_DISABLE', true); // Ön yüzde kapat
define('HEARTBEAT_INTERVAL_ADMIN', 60); // Admin için interval (saniye)
define('HEARTBEAT_INTERVAL_EDITOR', 30); // Editör sayfası için interval
function master_heartbeat_controller() {
global $pagenow;
// Ön yüzde kapat
if (defined('HEARTBEAT_FRONTEND_DISABLE') &&
HEARTBEAT_FRONTEND_DISABLE &&
!is_admin()) {
wp_deregister_script('heartbeat');
return;
}
if (!is_admin()) return;
// Editör sayfaları - heartbeat aktif, optimized interval
$editor_pages = ['post.php', 'post-new.php'];
if (in_array($pagenow, $editor_pages)) {
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = HEARTBEAT_INTERVAL_EDITOR;
return $settings;
});
return; // Bu sayfalarda aktif bırak
}
// WooCommerce sipariş sayfaları - aktif bırak
$post_type = isset($_GET['post_type']) ? sanitize_text_field($_GET['post_type']) : '';
if ($pagenow === 'edit.php' && $post_type === 'shop_order') {
add_filter('heartbeat_settings', function($settings) {
$settings['interval'] = HEARTBEAT_INTERVAL_ADMIN;
return $settings;
});
return;
}
// Diğer tüm admin sayfaları - kapat
wp_deregister_script('heartbeat');
}
add_action('init', 'master_heartbeat_controller', 1);
// Heartbeat aktifken bile gereksiz veri göndermesini engelle
add_filter('heartbeat_received', function($response, $data) {
// Sadece gerekli verilere izin ver
$allowed_keys = ['wp-auth-check', 'wp-refresh-post-lock', 'wp-check-locked-posts'];
foreach ($data as $key => $value) {
if (!in_array($key, $allowed_keys)) {
unset($response[$key]);
}
}
return $response;
}, 10, 2);
Dikkat Edilmesi Gereken Noktalar
Heartbeat API’yi kapatmak ya da kısıtlamak bazı sonuçlar doğurabilir. Bunlara hazırlıklı olun:
- Otomatik kaydetme çalışmaz: Editör dışındaki sayfalarda heartbeat kapatılınca otomatik taslak kaydetme de durur. Bu genellikle sorun değildir çünkü liste sayfalarında düzenleme yapmazsınız.
- Çoklu düzenleme uyarısı kaybolur: İki admin aynı yazıyı düzenlemeye çalıştığında uyarı gelmeyebilir. Küçük ekipler için sorun değil ama büyük editorial ekiplerinde dikkat edin.
- WooCommerce bildirimler: Bazı WooCommerce gerçek zamanlı bildirimleri heartbeat üzerinden çalışır. Kapatırsanız bu bildirimler gecikebilir.
- Üçüncü parti eklentiler: Bazı eklentiler heartbeat’i kendi iletişimleri için kullanır. Test ortamında mutlaka doğrulayın.
Değişiklik yaptıktan sonra en az 48 saat izleme yapın. Özellikle editörlük yapan kullanıcılardan geri bildirim alın.
Performans Kazanımı Ne Kadar Olur?
Kesin rakamlar vermek zor çünkü site trafiğine, eş zamanlı admin kullanıcı sayısına ve sunucu kapasitesine göre değişiyor. Ancak genel gözlemlerim şu yönde:
- Düşük trafikli blog sitelerde heartbeat optimizasyonu çok fark yaratmaz. Kaynak kullanımı zaten düşüktür.
- Orta ölçekli WooCommerce mağazalarda (günde 100+ sipariş) admin-ajax.php yükü %40-60 oranında azalır.
- Çok sayıda admin kullanıcısı olan büyük medya sitelerinde sunucu CPU kullanımında gözle görülür düşüş yaşanır.
- Paylaşımlı hostingde hemen fark edersiniz: Sayfa yüklenme süreleri kısalır.
Önemli bir not: Bu optimizasyon tek başına bir sihir değil. Caching, CDN, veritabanı optimizasyonu gibi diğer tekniklerle birlikte uygulandığında gerçek anlamda etkili olur. Heartbeat optimizasyonunu daha büyük bir performans stratejisinin parçası olarak görün.
Sonuç
WordPress Heartbeat API, yanlış yönetildiğinde sessiz bir kaynak katili olabilir. Doğru yönetildiğinde ise önemli bir performans kazanımı sağlayabilirsiniz. Burada anlattığım yaklaşımı özetleyeyim:
- Ön yüzde heartbeat’i tamamen kapatın, buna ihtiyaç yok
- Admin panelinde sadece gerçekten ihtiyaç duyulan sayfalarda (editör, WooCommerce) aktif bırakın
- Aktif kaldığı yerlerde interval değerini makul bir seviyeye çekin (30-60 saniye)
- Kullanıcı rollerine göre farklılaştırma yapın
- Değişikliklerinizi mutlaka test ortamında deneyin, ardından production’a alın
Bu işlemlerin tamamını bir eklenti üzerinden de yapabilirsiniz (Heartbeat Control gibi eklentiler var), ancak küçük bir functions.php kodu yeterliyken ekstra eklenti yüklemek benim tercihim değil. Kod basit, bakımı kolay ve tam kontrol sizde.
Siteye özgü ihtiyaçlarınıza göre bu kodları uyarlayın. Her WordPress kurulumu farklıdır ve tek bir çözüm herkese uymaz. Deneyip gözlemleyin, gerekirse ayarlayın.
