<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PluginLab</title>
    <description>The latest articles on DEV Community by PluginLab (@pluginlab).</description>
    <link>https://dev.to/pluginlab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4236854%2F0ac1f772-985e-4a39-bb9f-55b7e0306d2d.webp</url>
      <title>DEV Community: PluginLab</title>
      <link>https://dev.to/pluginlab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pluginlab"/>
    <language>en</language>
    <item>
      <title>WordPress Heartbeat API: What It Does and When to Slow It Down</title>
      <dc:creator>PluginLab</dc:creator>
      <pubDate>Tue, 10 Nov 2026 11:14:10 +0000</pubDate>
      <link>https://dev.to/pluginlab/wordpress-heartbeat-api-what-it-does-and-when-to-slow-it-down-1h9l</link>
      <guid>https://dev.to/pluginlab/wordpress-heartbeat-api-what-it-does-and-when-to-slow-it-down-1h9l</guid>
      <description>&lt;p&gt;If you have ever opened your browser's network tab on a WordPress admin screen, you have seen a request to &lt;code&gt;admin-ajax.php&lt;/code&gt; that keeps repeating on its own. That is the Heartbeat API. It is part of WordPress core, it is on by default, and it is one of the most misunderstood things people switch off. &lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://pluginlab.dev/plugins/slimpress/" rel="noopener noreferrer"&gt;SlimPress&lt;/a&gt; to turn off parts of core that a site does not use, with each switch explaining what it might break. Heartbeat is a good example of why that explanation matters, because the right answer is not always "off". &lt;/p&gt;

&lt;h2&gt;
  
  
  What the Heartbeat API does
&lt;/h2&gt;

&lt;p&gt;Heartbeat is a small timer in the browser. While a logged-in user has a WordPress screen open, it sends a request to your server every so often (roughly every 15 to 60 seconds, depending on the screen) and lets WordPress and plugins send data back. In core it is used for three things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autosave&lt;/strong&gt; of the post you are editing. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post locking&lt;/strong&gt;, so two people do not overwrite each other, and the "someone else is editing this" notice. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Login expiry&lt;/strong&gt;, the prompt that asks you to log in again without losing your work. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plugins can hook into it too, for example to refresh a live counter or a notification badge in the dashboard. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why it can matter for server load
&lt;/h2&gt;

&lt;p&gt;Every heartbeat is a full WordPress request. One editor with a tab open is nothing. A handful of staff who leave the dashboard open all day on a small shared host, or a shop where several people sit on the orders screen, add up to a steady trickle of &lt;code&gt;admin-ajax.php&lt;/code&gt; calls that never stops. On a well-resourced server you will not notice it. On a weak one, it is often what you see when you check what is hitting the site while nobody is visiting. &lt;/p&gt;

&lt;p&gt;I will not give you a speed-up figure for it, because it depends entirely on your hosting, how many people are logged in and what your plugins add to each beat. If you want a number for your own site, the performance test in SlimPress compares your pages with and without its features in the same run, and says "within noise" when the difference is too small to trust. &lt;/p&gt;

&lt;h2&gt;
  
  
  Slow it down, or turn it off?
&lt;/h2&gt;

&lt;p&gt;These are different choices, and they have different costs. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Leave it alone&lt;/strong&gt; if you edit content regularly, have more than one author, or run plugins that show live data in the admin. Autosave and post locking are useful. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limit it by location&lt;/strong&gt; if you want the saving without the constant background chatter. SlimPress has a Heartbeat switch per location, so you can treat different parts of the site differently instead of one on/off for everything. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn it off in a location&lt;/strong&gt; only where you know nothing there needs it, for example a screen where nobody writes content. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Switching it off completely is the option that costs you the most. Without it you lose the protections above in that location. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to change it with SlimPress
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install and activate SlimPress. Nothing changes on activation; every switch starts off. &lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings → SlimPress&lt;/strong&gt; and open the &lt;strong&gt;APIs &amp;amp; connections&lt;/strong&gt; group. &lt;/li&gt;
&lt;li&gt;Find the Heartbeat switches. Each one lists what it does and what might break, so read that before you save. &lt;/li&gt;
&lt;li&gt;Save, then use the site as you normally would. Open a post, edit it, and check that you are still seeing autosave and the editing notices where you expect them. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SlimPress also warns you if an active plugin is known to rely on something you are about to switch off. &lt;/p&gt;

&lt;h2&gt;
  
  
  What can break
&lt;/h2&gt;

&lt;p&gt;The risk is concentrated in two places. If you turn Heartbeat off where people edit posts, autosave and post locking stop working there, so a browser crash costs more work and two editors can overwrite each other. And if a plugin of yours uses Heartbeat for live updates in the admin, those updates stop refreshing by themselves. Neither failure is loud, which is why I would test with a real post after changing it rather than assume. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to undo it
&lt;/h2&gt;

&lt;p&gt;SlimPress keeps the last 10 versions of its settings. Open &lt;strong&gt;Tools → Undo a change&lt;/strong&gt; and restore an earlier version, whether the change was a single save, a preset or a reset. If you are not sure which switch caused a problem, pause one group at a time from its tab to find out. Every switch is a runtime filter, so deactivating the plugin puts WordPress back to its default behaviour on the next request. Nothing is written to core settings. &lt;/p&gt;

&lt;h2&gt;
  
  
  When another approach is better
&lt;/h2&gt;

&lt;p&gt;If you only want Heartbeat tamed and nothing else, a plugin dedicated to that one job may be all you need, and a few lines of code in a small custom plugin can do it too. SlimPress makes sense when Heartbeat is one of several core features you want to review with the risks spelled out. It deliberately does not do caching, minification or script delaying, so it will not replace a performance plugin for those. &lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Heartbeat powers autosave, post locking and login-expiry prompts in the admin. &lt;/li&gt;
&lt;li&gt;It matters mostly on weak hosting with several people keeping the dashboard open. &lt;/li&gt;
&lt;li&gt;Limit it where you can; turn it off only where nothing needs it, and test with a real post. &lt;/li&gt;
&lt;li&gt;You can undo any change from the Tools tab. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SlimPress is free on &lt;a href="https://wordpress.org/plugins/slimpress/" rel="noopener noreferrer"&gt;WordPress.org&lt;/a&gt;, with no pro tier and no telemetry. Support happens in the &lt;a href="https://wordpress.org/support/plugin/slimpress/" rel="noopener noreferrer"&gt;WordPress.org forums&lt;/a&gt;, in public.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://pluginlab.dev/blog/wordpress-heartbeat-api/" rel="noopener noreferrer"&gt;pluginlab.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Selling Event Tickets With QR Codes in WooCommerce, Without a Ticketing Service</title>
      <dc:creator>PluginLab</dc:creator>
      <pubDate>Tue, 10 Nov 2026 11:08:04 +0000</pubDate>
      <link>https://dev.to/pluginlab/selling-event-tickets-with-qr-codes-in-woocommerce-without-a-ticketing-service-3i0g</link>
      <guid>https://dev.to/pluginlab/selling-event-tickets-with-qr-codes-in-woocommerce-without-a-ticketing-service-3i0g</guid>
      <description>&lt;p&gt;If you run a venue, an escape room, a museum or a club with a WooCommerce shop, you have probably looked at ticketing services. They work, but they take a fee on every ticket, they put someone else's brand in the middle of your checkout, and your customer list ends up on their platform. &lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://pluginlab.dev/plugins/tickets-passes/" rel="noopener noreferrer"&gt;Tickets &amp;amp; Passes for WooCommerce&lt;/a&gt; for shops where the sale already happens in WooCommerce and the only missing piece is: how does a person get in the door? Here is how it works from sale to scan. &lt;/p&gt;

&lt;h2&gt;
  
  
  Three product types, one dropdown
&lt;/h2&gt;

&lt;p&gt;After you activate the plugin and turn on the types you need, three new options appear in the same &lt;strong&gt;Product data&lt;/strong&gt; dropdown that holds Simple and Variable: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ticket&lt;/strong&gt;: plain admission with a validity window and a set number of uses. Day tickets, entry tickets, gift admission. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeslot Ticket&lt;/strong&gt;: admission for a specific date and time, with a capacity per slot. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pass&lt;/strong&gt;: valid across a period rather than one visit. Season passes, memberships, annual cards. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three can sit in the same cart and the same order as your normal products, so selling a ticket and a T-shirt together just works. &lt;/p&gt;

&lt;h2&gt;
  
  
  What the customer gets
&lt;/h2&gt;

&lt;p&gt;Every purchase issues a QR code. Customers see it in the order confirmation email, on a new &lt;strong&gt;Tickets&lt;/strong&gt; or &lt;strong&gt;Passes&lt;/strong&gt; tab in WooCommerce My Account, and as a printable PDF. Each ticket shows its live status (active, used, expired, cancelled or not valid yet) and how many uses are left. Timeslot tickets include an Add to Calendar file. &lt;/p&gt;

&lt;p&gt;The QR codes and PDFs are not stored at a guessable public URL. They are served through the plugin, which checks the request is coming from a signed link in the customer's email or from the signed-in owner. That also means a page cache or CDN will not hand one customer's ticket to another visitor. &lt;/p&gt;

&lt;h2&gt;
  
  
  Timeslots without building next month by hand
&lt;/h2&gt;

&lt;p&gt;For anything with a limited capacity per session, Timeslot Tickets let you generate slots on a repeating schedule. Capacity is checked when the item goes into the cart, not only after payment. Reservations that are never paid for are released automatically, so an abandoned checkout does not hold a seat. &lt;/p&gt;

&lt;h2&gt;
  
  
  Passes, guest passes and photo check
&lt;/h2&gt;

&lt;p&gt;A Pass can include guest passes that the holder hands out from their account page, collect a cardholder photo at purchase, and enforce a cooldown between scans. At the door, staff see the photo next to the scan result and can compare it with the person standing there. &lt;/p&gt;

&lt;h2&gt;
  
  
  Scanning at the door
&lt;/h2&gt;

&lt;p&gt;This is the part people expect to need an app. It does not: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The scanner is a full-screen page on your own domain, at &lt;code&gt;/check-in/&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Door staff open it in a phone browser and point the camera at the QR code. It needs HTTPS, because phone browsers only give camera access to secure pages. &lt;/li&gt;
&lt;li&gt;Results are colour-coded and you choose the colours: valid, already used, expired, on cooldown or not found. &lt;/li&gt;
&lt;li&gt;Give staff the &lt;strong&gt;Scanner&lt;/strong&gt; user role and they can check people in without seeing anything else in wp-admin. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every decision is made on your server, not on the phone. A cancelled ticket cannot be waved through by putting the phone in airplane mode, because the check has to reach your site. If there is no camera, a code can be typed in, and manual check-in is available from the dashboard. &lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;The plugin is free, and there is no fee per ticket. You sell through your own WooCommerce checkout, so what you charge is what you keep. You still pay your payment processor's normal fees, as with any WooCommerce sale. There is no pro version, no telemetry, and the code is readable and unminified. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup in five steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install and activate the plugin with WooCommerce already active. &lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Ticket &amp;amp; Passes → Settings&lt;/strong&gt; and enable the product types you need. &lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Scanner / API&lt;/strong&gt; tab, turn on the scanner. The tab shows your scanner URL. &lt;/li&gt;
&lt;li&gt;Create a product and pick Ticket, Timeslot Ticket or Pass from the Product data dropdown. &lt;/li&gt;
&lt;li&gt;Set door staff to the Scanner role. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where a hosted service is still better
&lt;/h2&gt;

&lt;p&gt;If you need a marketplace where strangers discover your event, or you do not already run a WooCommerce shop, a hosted ticketing service gives you that audience and the setup for free. This plugin is for the case where people already come to your own site and you would rather keep the fee and the customer relationship. &lt;/p&gt;

&lt;p&gt;Tickets &amp;amp; Passes is on &lt;a href="https://wordpress.org/plugins/tickets-passes-for-woocommerce/" rel="noopener noreferrer"&gt;WordPress.org&lt;/a&gt;. Support is in the public forums, where the next person with your question can read the answer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://pluginlab.dev/blog/woocommerce-qr-code-tickets/" rel="noopener noreferrer"&gt;pluginlab.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Disable XML-RPC in WordPress Without Breaking Anything</title>
      <dc:creator>PluginLab</dc:creator>
      <pubDate>Tue, 10 Nov 2026 11:08:01 +0000</pubDate>
      <link>https://dev.to/pluginlab/how-to-disable-xml-rpc-in-wordpress-without-breaking-anything-h7c</link>
      <guid>https://dev.to/pluginlab/how-to-disable-xml-rpc-in-wordpress-without-breaking-anything-h7c</guid>
      <description>&lt;p&gt;XML-RPC is an old remote-access door into WordPress, a single file called &lt;code&gt;xmlrpc.php&lt;/code&gt; in your site root. It has been switched on by default for years, and most sites have never used it. Security guides tell you to turn it off. What they usually skip is the part that matters: what stops working when you do. &lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://pluginlab.dev/plugins/slimpress/" rel="noopener noreferrer"&gt;SlimPress&lt;/a&gt; because I kept turning off the same parts of WordPress core on shop sites and wanted each switch to say what it might break. XML-RPC is one of the first ones people ask about, so here is the full picture. &lt;/p&gt;

&lt;h2&gt;
  
  
  What XML-RPC is used for
&lt;/h2&gt;

&lt;p&gt;Before XML-RPC existed as a thing to worry about, it was how outside software talked to WordPress. Today three things still use it: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The WordPress mobile app&lt;/strong&gt;, on some setups, to publish and manage posts. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jetpack&lt;/strong&gt;, which uses it to connect your site to WordPress.com. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pingbacks and trackbacks&lt;/strong&gt;, the notifications between blogs that link to each other. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some older desktop publishing tools and a few third-party services also use it. If none of the above applies to you, nothing on your site is likely to miss it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why people turn it off
&lt;/h2&gt;

&lt;p&gt;Two reasons come up repeatedly. First, XML-RPC accepts login attempts, and it can bundle many of them into one request, which makes it a convenient target for password guessing. Second, pingbacks can be abused to make your site send requests to other places. Neither is a reason to panic, but if you are not using the feature, there is nothing to gain from leaving it exposed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: check whether anything uses it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Plugins&lt;/strong&gt; and look for Jetpack or any plugin that mentions WordPress.com, remote publishing or a mobile app. &lt;/li&gt;
&lt;li&gt;Ask yourself whether anyone posts to the site from the WordPress mobile app or an old desktop editor. &lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Settings → Discussion&lt;/strong&gt;. If "Allow link notifications from other blogs (pingbacks and trackbacks)" is ticked and you care about those, keep that in mind. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the answer to all three is no, you can switch it off. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: switch it off
&lt;/h2&gt;

&lt;p&gt;You can do this with a code snippet or a &lt;code&gt;.htaccess&lt;/code&gt; rule, but then it is hard to remember later that you did it, and harder to undo. With SlimPress it is one switch: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install and activate &lt;a href="https://wordpress.org/plugins/slimpress/" rel="noopener noreferrer"&gt;SlimPress&lt;/a&gt;. Activation changes nothing on its own. &lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings → SlimPress&lt;/strong&gt; and open the &lt;strong&gt;APIs &amp;amp; connections&lt;/strong&gt; group. &lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Disable XML-RPC&lt;/strong&gt;. It is marked &lt;em&gt;Careful&lt;/em&gt;, and the note under it lists what might break: the WordPress mobile app, Jetpack and pingbacks. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SlimPress also warns you if an active plugin is known to rely on the feature you are about to switch off, so Jetpack on the same site would show up before you save. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: confirm it worked
&lt;/h2&gt;

&lt;p&gt;Visit &lt;code&gt;yoursite.com/xmlrpc.php&lt;/code&gt;. On a default WordPress site you will see the message "XML-RPC server accepts POST requests only." After the switch is on, that page should no longer behave like a working XML-RPC endpoint. Then open your site's front end and the dashboard to make sure nothing looks different. For most sites, nothing will. &lt;/p&gt;

&lt;h2&gt;
  
  
  If something stops working
&lt;/h2&gt;

&lt;p&gt;This is the part I care about most. SlimPress keeps the last 10 versions of its settings, so any save can be undone, and every switch is a runtime filter. Deactivating the plugin puts WordPress back to its default behaviour on the next request. There is nothing in your database to clean up. &lt;/p&gt;

&lt;p&gt;If Jetpack complains after the change, turn the switch off again and reconnect it. If you want to keep Jetpack and still reduce exposure, the better route is to leave XML-RPC on and add rate limiting at your firewall or host. &lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check for Jetpack, the mobile app and pingbacks first. &lt;/li&gt;
&lt;li&gt;If you use none of them, turn XML-RPC off. &lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;/xmlrpc.php&lt;/code&gt; afterwards, and know how to undo it. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SlimPress is free, with no pro tier and no telemetry. Support happens in the &lt;a href="https://wordpress.org/support/plugin/slimpress/" rel="noopener noreferrer"&gt;WordPress.org forums&lt;/a&gt;, in public.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://pluginlab.dev/blog/disable-xml-rpc-wordpress/" rel="noopener noreferrer"&gt;pluginlab.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
