<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Pier — Blog</title>
    <link>https://pier.abn.company/blog/</link>
    <atom:link href="https://pier.abn.company/blog/feed.xml" rel="self" type="application/rss+xml" />
    <description>Practical writing on legacy websites, FTP, MySQL and AI-assisted edits.</description>
    <language>en</language>
    <copyright>© 2026 A Brand New Company B.V.</copyright>
    <lastBuildDate>Fri, 12 Jun 2026 01:23:38 GMT</lastBuildDate>
    <generator>pier-blog-bot</generator>
    <image>
      <url>https://pier.abn.company/logo.svg</url>
      <title>Pier — Blog</title>
      <link>https://pier.abn.company/blog/</link>
    </image>
    
    <item>
      <title>Joomla 4 500 after Akeeba restore: the missing action_logs fix</title>
      <link>https://pier.abn.company/blog/joomla-akeeba-action-logs-fix/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/joomla-akeeba-action-logs-fix/</guid>
      <description>A routine Akeeba restore. A blank white 500. Forty minutes of grep, schema reconstruction and one quiet INSERT later, the Joomla 4 site was back.</description>
      <category>Joomla</category>
      <pubDate>Fri, 12 Jun 2026 01:23:37 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>PHP 7.4 to 8.2 upgrade: a pre-flight audit checklist</title>
      <link>https://pier.abn.company/blog/php-74-to-82-audit-checklist/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/php-74-to-82-audit-checklist/</guid>
      <description>You said yes to the PHP 8.2 jump on a ten-year-old WordPress install. Before the maintenance window opens, here is the audit that keeps it boring.</description>
      <category>PHP</category>
      <pubDate>Fri, 12 Jun 2026 00:27:57 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Drupal watchdog by hand: severity, type, four queries</title>
      <link>https://pier.abn.company/blog/drupal-watchdog-severity-queries/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/drupal-watchdog-severity-queries/</guid>
      <description>The dblog admin page caps at 50 rows and aggregates nothing. The watchdog table itself answers the questions the UI cannot. Three columns and four queries.</description>
      <category>Drupal</category>
      <pubDate>Thu, 11 Jun 2026 23:37:44 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>wp-config.php debug constants: the nine we always set</title>
      <link>https://pier.abn.company/blog/wp-config-debug-constants/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/wp-config-debug-constants/</guid>
      <description>A site lands in your inbox: SFTP creds, vague symptoms, no documentation. Before reading a line of someone else&#39;s plugin code, we set nine wp-config constants.</description>
      <category>WordPress</category>
      <pubDate>Thu, 11 Jun 2026 22:49:41 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>WordPress multisite migration: the one-Sunday playbook</title>
      <link>https://pier.abn.company/blog/wordpress-multisite-plesk-vps-migration/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/wordpress-multisite-plesk-vps-migration/</guid>
      <description>A Plesk box on PHP 7.4 with a 12-site multisite, a fresh VPS waiting at Hetzner, and a Sunday from 09:00 to 17:00 to get the cutover done before Monday traffic.</description>
      <category>WordPress</category>
      <pubDate>Thu, 11 Jun 2026 22:01:03 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Symfony 6 intranet migration: eleven weekends, zero downtime</title>
      <link>https://pier.abn.company/blog/symfony-6-intranet-migration/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/symfony-6-intranet-migration/</guid>
      <description>Eleven weekends, one strangler proxy, and a timesheet form that never went dark. How an in-house team moved a 2011 custom-PHP intranet onto Symfony 6 without anyone noticing.</description>
      <category>Migration</category>
      <pubDate>Thu, 11 Jun 2026 21:05:12 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Magento 2 cron_schedule at 14M rows: a Friday postmortem</title>
      <link>https://pier.abn.company/blog/magento-2-cron-schedule-bloat/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/magento-2-cron-schedule-bloat/</guid>
      <description>A Magento 2 shop&#39;s cron_schedule table hit 14 million rows on a Friday afternoon. Here is the prune, the lock duration we accepted, and the indexer config that stopped the regrowth.</description>
      <category>Magento</category>
      <pubDate>Thu, 11 Jun 2026 20:13:18 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Contact form spam: a 30-minute incident walkthrough</title>
      <link>https://pier.abn.company/blog/contact-form-spam-incident-response/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/contact-form-spam-incident-response/</guid>
      <description>23:41 on a Tuesday. A legacy WordPress contact form just became an open relay and the host has fifteen minutes of patience. Here is the thirty-minute IR.</description>
      <category>Security</category>
      <pubDate>Thu, 11 Jun 2026 19:20:22 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>WordPress nonces: what wp_verify_nonce actually does</title>
      <link>https://pier.abn.company/blog/wordpress-nonces-fundamentals/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/wordpress-nonces-fundamentals/</guid>
      <description>The form works in the morning, breaks in the afternoon, and nobody can reproduce it on demand. The bug is in how you read what wp_verify_nonce returns.</description>
      <category>WordPress</category>
      <pubDate>Thu, 11 Jun 2026 18:25:54 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>osCommerce to WooCommerce: six weekends, no SEO loss</title>
      <link>https://pier.abn.company/blog/oscommerce-to-woocommerce-migration/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/oscommerce-to-woocommerce-migration/</guid>
      <description>A 14-year-old osCommerce store moved onto WooCommerce in six weekends. The URL map, the specials-to-sale-price bridge, and the SEO that kept its rankings.</description>
      <category>Migration</category>
      <pubDate>Thu, 11 Jun 2026 17:38:22 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>PHP-FPM pool sizing: 2GB, 4GB and 8GB VPS, compared</title>
      <link>https://pier.abn.company/blog/php-fpm-pool-sizing-vps/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/php-fpm-pool-sizing-vps/</guid>
      <description>A WooCommerce shop crashes at lunch. PHP-FPM is at 100% pool capacity and the host wants you to size up the VPS. Before you click, here&#39;s the math.</description>
      <category>Operations</category>
      <pubDate>Thu, 11 Jun 2026 16:49:40 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Magento 1 AI product copy: a staging shape that holds</title>
      <link>https://pier.abn.company/blog/magento-ai-copy-staging-shape/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/magento-ai-copy-staging-shape/</guid>
      <description>A read-only staging mirror is the cheapest insurance against AI-generated product copy that overwrites the wrong SKU in a 2014-vintage Magento store.</description>
      <category>AI</category>
      <pubDate>Thu, 11 Jun 2026 15:59:34 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Inheriting a legacy site: the one-page handover audit</title>
      <link>https://pier.abn.company/blog/legacy-site-handover-audit/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/legacy-site-handover-audit/</guid>
      <description>You inherited a WordPress site from another agency. The code looks fine. Then the SSL silently fails on a server nobody mentioned. Here is the audit we run.</description>
      <category>Workflow</category>
      <pubDate>Thu, 11 Jun 2026 15:07:35 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Cache-Control leak: the missing word that cached sessions</title>
      <link>https://pier.abn.company/blog/cache-control-leaked-php-sessions/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/cache-control-leaked-php-sessions/</guid>
      <description>At 16:47 a customer screenshotted someone else&#39;s order history in his own dashboard. The bug was a Cache-Control header on the PHP account page, missing one word.</description>
      <category>PHP</category>
      <pubDate>Thu, 11 Jun 2026 14:18:55 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Joomla 3 #__extensions table: a six-column field guide</title>
      <link>https://pier.abn.company/blog/joomla-extensions-table-field-guide/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/joomla-extensions-table-field-guide/</guid>
      <description>Six columns in #__extensions tell you everything Joomla actually loads. A field guide for the moment you take over a site whose admin won&#39;t open.</description>
      <category>Joomla</category>
      <pubDate>Thu, 11 Jun 2026 13:28:09 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>mysqldump flags for legacy MySQL: the .my.cnf cheatsheet</title>
      <link>https://pier.abn.company/blog/mysqldump-flags-legacy-mysql/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/mysqldump-flags-legacy-mysql/</guid>
      <description>The .my.cnf and mysqldump flags we drop on every legacy MySQL box before an export, and the three that have saved a restore at two in the morning.</description>
      <category>Databases</category>
      <pubDate>Thu, 11 Jun 2026 12:36:41 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Drupal 7 to static on Cloudflare Pages: a 2-hour playbook</title>
      <link>https://pier.abn.company/blog/drupal-7-static-cloudflare-pages-playbook/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/drupal-7-static-cloudflare-pages-playbook/</guid>
      <description>Drupal 7 reached end of life. You inherited one. Here&#39;s a two-hour route to a static export on Cloudflare Pages with the contact form still working.</description>
      <category>Drupal</category>
      <pubDate>Thu, 11 Jun 2026 11:47:38 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Magento sales_order_grid: the staged 4GB shrink we ran</title>
      <link>https://pier.abn.company/blog/magento-sales-order-grid-shrink/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/magento-sales-order-grid-shrink/</guid>
      <description>A Dutch agency we work with had a sales_order_grid pushing 4GB after Black Friday. Here is the staged shrink that took it back to lean, with every archived order intact.</description>
      <category>Magento</category>
      <pubDate>Thu, 11 Jun 2026 10:57:12 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>WooCommerce double-charge: tracing a duplicate Stripe hook</title>
      <link>https://pier.abn.company/blog/woocommerce-stripe-double-charge-hook/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/woocommerce-stripe-double-charge-hook/</guid>
      <description>Two payment intents, three seconds apart, same order, same card. An incident walkthrough of a duplicate woocommerce_payment_complete hook hiding in mu-plugins.</description>
      <category>WordPress</category>
      <pubDate>Thu, 11 Jun 2026 10:04:47 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Legacy site monitoring: the four-signal stack for solo shops</title>
      <link>https://pier.abn.company/blog/legacy-site-monitoring-stack/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/legacy-site-monitoring-stack/</guid>
      <description>Thirty legacy sites, one person, and a Sunday morning that started with a &#39;checkout broken since Friday&#39; Slack. Four signals would have caught it on Thursday.</description>
      <category>Operations</category>
      <pubDate>Thu, 11 Jun 2026 09:10:05 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Statamic migration freeze: a five-day editorial playbook</title>
      <link>https://pier.abn.company/blog/statamic-migration-freeze-playbook/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/statamic-migration-freeze-playbook/</guid>
      <description>The staged content-freeze playbook for a five-day legacy-to-Statamic cutover: editorial lock, three diff checkpoints, the .htaccess that ships.</description>
      <category>Workflow</category>
      <pubDate>Thu, 11 Jun 2026 08:18:43 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>PHP session race: the case of the wrong invoice PDF</title>
      <link>https://pier.abn.company/blog/php-session-race-invoice-pdf/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/php-session-race-invoice-pdf/</guid>
      <description>A Dutch agency we work with rang at 23:41. Their custom-PHP billing portal had emailed the wrong invoice PDF to a customer. We blamed session_start for six hours.</description>
      <category>PHP</category>
      <pubDate>Thu, 11 Jun 2026 07:27:28 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Magento 1 chatbot: the read-only shape that survives</title>
      <link>https://pier.abn.company/blog/magento-1-chatbot-read-only-shape/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/magento-1-chatbot-read-only-shape/</guid>
      <description>A client wants a chatbot bolted onto a 2017 Magento 1 store. The trick is keeping it read-only, off the checkout path, and out of the order tables.</description>
      <category>AI</category>
      <pubDate>Thu, 11 Jun 2026 06:33:03 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Xdebug 3 over an SSH tunnel: the SFTP-only setup</title>
      <link>https://pier.abn.company/blog/xdebug-3-ssh-tunnel-sftp/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/xdebug-3-ssh-tunnel-sftp/</guid>
      <description>A working Xdebug 3 setup against a remote SFTP-only host, with the tunnel direction, path map and idekey gotchas spelled out so you don&#39;t lose an afternoon.</description>
      <category>PHP</category>
      <pubDate>Thu, 11 Jun 2026 05:41:34 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Curl recon for legacy sites: seven one-liners before quoting</title>
      <link>https://pier.abn.company/blog/curl-recon-legacy-hardening/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/curl-recon-legacy-hardening/</guid>
      <description>An agency drops a URL into the brief at 23:41 and asks for a hardening quote by morning. Seven curl one-liners take five minutes and size the work honestly.</description>
      <category>Security</category>
      <pubDate>Thu, 11 Jun 2026 04:51:26 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Joomla 3 image library to S3: a 22GB migration log</title>
      <link>https://pier.abn.company/blog/joomla-image-library-to-s3/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/joomla-image-library-to-s3/</guid>
      <description>How we moved a 22GB Joomla 3 image library to S3 over one weekend, without breaking a single article reference or noticing a flicker in the access log.</description>
      <category>Migration</category>
      <pubDate>Thu, 11 Jun 2026 03:58:08 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>WordPress functions.php hack: a four-pass cleanup playbook</title>
      <link>https://pier.abn.company/blog/wordpress-functions-php-hack-cleanup/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/wordpress-functions-php-hack-cleanup/</guid>
      <description>A hacked theme functions.php is rarely alone. Here is the four-pass cleanup we run on WordPress sites before anyone goes near wp-options or wp-posts.</description>
      <category>WordPress</category>
      <pubDate>Thu, 11 Jun 2026 03:03:44 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Reading mysqlbinlog: a field guide to row-format events</title>
      <link>https://pier.abn.company/blog/reading-mysqlbinlog-row-events/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/reading-mysqlbinlog-row-events/</guid>
      <description>An agency lead pings at 23:41: someone swapped wp_options.siteurl, the web logs are clean. Here is how to read mysqlbinlog row events and find them.</description>
      <category>Databases</category>
      <pubDate>Thu, 11 Jun 2026 02:12:44 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>Drupal 9 502 for editors only: a session table outage</title>
      <link>https://pier.abn.company/blog/drupal-9-session-table-outage/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/drupal-9-session-table-outage/</guid>
      <description>A Drupal 9 site started 502ing only for logged-in editors on a Thursday afternoon. Anonymous traffic was fine. The cause was a sessions table that had outgrown ibdata1.</description>
      <category>Drupal</category>
      <pubDate>Thu, 11 Jun 2026 01:20:50 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>

    <item>
      <title>TLS handover checklist: cert, chain, cron, four hidden traps</title>
      <link>https://pier.abn.company/blog/tls-handover-checklist/</link>
      <guid isPermaLink="true">https://pier.abn.company/blog/tls-handover-checklist/</guid>
      <description>A one-page TLS handover checklist for inherited sites. The leaf, the chain, the cron and the four hidden traps hosts forget to mention at handover.</description>
      <category>Security</category>
      <pubDate>Thu, 11 Jun 2026 00:28:09 GMT</pubDate>
      <dc:creator>Pier editorial</dc:creator>
    </item>
  </channel>
</rss>
