<?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: Choaib Mouhrach</title>
    <description>The latest articles on DEV Community by Choaib Mouhrach (@choaibmouhrach).</description>
    <link>https://dev.to/choaibmouhrach</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F959276%2F032b9a39-5f6b-489e-b109-d6194e47b89f.png</url>
      <title>DEV Community: Choaib Mouhrach</title>
      <link>https://dev.to/choaibmouhrach</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/choaibmouhrach"/>
    <language>en</language>
    <item>
      <title>The 5 things that actually break in a Moodle 5.1 5.2 upgrade</title>
      <dc:creator>Choaib Mouhrach</dc:creator>
      <pubDate>Wed, 23 Sep 2026 22:20:15 +0000</pubDate>
      <link>https://dev.to/choaibmouhrach/the-5-things-that-actually-break-in-a-moodle-51-52-upgrade-4ba4</link>
      <guid>https://dev.to/choaibmouhrach/the-5-things-that-actually-break-in-a-moodle-51-52-upgrade-4ba4</guid>
      <description>&lt;p&gt;Every "mysterious" Moodle 5.2 upgrade failure I've debugged has come down to the same five things.&lt;/p&gt;

&lt;p&gt;Not ten, not fifty. Five.&lt;/p&gt;

&lt;p&gt;If your site broke after upgrading from 5.1, check these before you start touching the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The web root isn't pointing at &lt;code&gt;public&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is one of the most common causes of Moodle 5.x upgrade problems. Since Moodle 5.1, the web-accessible code lives under &lt;code&gt;public/&lt;/code&gt;. If your vhost is still pointing to the parent directory, you'll get 404s, failed security checks, and other weird errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;
&lt;span class="nc"&gt;DocumentRoot&lt;/span&gt; /var/www/moodle/public

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;
&lt;span class="k"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/moodle/public&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're on cPanel or shared hosting and can't edit the vhost, you'll need a configurable docroot, a symlink, or a location alias. If your host doesn't support any of those, that's a hosting limitation, not a Moodle problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The router isn't forwarding requests to &lt;code&gt;r.php&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Moodle 5.1+ sends non-file requests through &lt;code&gt;r.php&lt;/code&gt;. If that's not configured properly, you'll see 404s, missing assets, and router errors in the environment check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;
&lt;span class="nc"&gt;FallbackResource&lt;/span&gt; /r.php

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;
&lt;span class="k"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/r.php&lt;/span&gt;&lt;span class="nv"&gt;$is_args$args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing that can be confusing here: if a &lt;code&gt;.php&lt;/code&gt;-looking route returns a 404 instead of a 302, PHP-FPM may be handling the missing path before Apache gets a chance to fall back to &lt;code&gt;r.php&lt;/code&gt;. That's a separate issue and needs to be debugged on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Composer dependencies are missing
&lt;/h2&gt;

&lt;p&gt;Moodle 5.1+ expects the &lt;code&gt;vendor/&lt;/code&gt; directory to be there. If it's missing, you'll get Composer errors during startup.&lt;/p&gt;

&lt;p&gt;From the Moodle root, not &lt;code&gt;public&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="nt"&gt;--classmap-authoritative&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No shell access? Build the release somewhere else and upload the complete Moodle codebase, including &lt;code&gt;vendor/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A plugin is still using old class names
&lt;/h2&gt;

&lt;p&gt;A classic example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Class "Mustache_Engine" not found

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get this after an otherwise successful core upgrade, it's not necessarily a database problem. Moodle 5.2 uses namespaced Mustache classes, so an older plugin or theme that still calls the old class name can break the site.&lt;/p&gt;

&lt;p&gt;Update or remove the offending plugin on staging and make sure you're using a release that actually supports Moodle 5.2.&lt;/p&gt;

&lt;p&gt;Also, don't take a clean file copy as proof that a plugin is compatible. Check every non-core plugin against the Moodle version you're upgrading to.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Caches weren't properly cleared
&lt;/h2&gt;

&lt;p&gt;After a clean upgrade, a lot of "this feature is broken" reports are just stale caches.&lt;/p&gt;

&lt;p&gt;The file picker refusing to load is a good example.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
php admin/cli/upgrade.php

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go to &lt;strong&gt;Site administration &amp;gt; Development &amp;gt; Purge all caches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On production, I'd use the CLI where possible. It avoids the browser, proxy, and timeout issues you can run into with the web upgrader on larger sites.&lt;/p&gt;




&lt;p&gt;Check these five things first and a lot of Moodle 5.2 upgrade problems become much easier to track down.&lt;/p&gt;

&lt;p&gt;Also, before you upgrade, back up all three:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;li&gt;&lt;code&gt;moodledata&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Having a copy of the files alone isn't a rollback plan.&lt;/p&gt;

&lt;p&gt;And always test the upgrade on a copy of the site before doing it in production.&lt;/p&gt;

&lt;p&gt;I wrote the full step-by-step guide here, including the server requirements, clean code replacement process, a symptom-to-cause table, and when it's time to stop and roll back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rizon.agency/blog/moodle-5-2-upgrade-guide" rel="noopener noreferrer"&gt;Moodle 5.1 to 5.2 Upgrade Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>moodle</category>
      <category>php</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Navigating Email Scheduling: Tackling Every Hurdle</title>
      <dc:creator>Choaib Mouhrach</dc:creator>
      <pubDate>Thu, 21 Mar 2024 03:06:07 +0000</pubDate>
      <link>https://dev.to/choaibmouhrach/navigating-email-scheduling-tackling-every-hurdle-5c11</link>
      <guid>https://dev.to/choaibmouhrach/navigating-email-scheduling-tackling-every-hurdle-5c11</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;Following the seamless transition from QSTASH to a VPS, and with the application running smoothly, I received referrals from a satisfied client to three more potential clients. They expressed interest in having the same application with additional features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background:
&lt;/h2&gt;

&lt;p&gt;This led me to launch three new containers, each with its subdomain for every client and interconnected via Caddy. However, this process unearthed more challenges than expected, particularly regarding resource allocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cumbersome Email Scheduling:
&lt;/h3&gt;

&lt;p&gt;Upon consulting with the new clients, I discovered they desired the ability to specify both the hour and minute for their emails. However, after delving deeper into their needs, I realized they sought to send emails at regular intervals. This prompted a revamp of the scheduling mechanism, transitioning from setting numerous timestamps to simply specifying a custom duration for email dispatch. This optimization not only streamlined the cron jobs but also enhanced performance and user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Management:
&lt;/h3&gt;

&lt;p&gt;Each container operated its own Postgres database and cron jobs, resulting in redundant resource consumption. To address this, I transformed the system into a multi-user setup with a single container and a shared database, akin to modern SaaS applications. This consolidation significantly reduced resource wastage and improved cron scheduling efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailored Features for Each Client:
&lt;/h3&gt;

&lt;p&gt;The transition to a SaaS-like architecture not only resolved resource inefficiencies but also simplified feature deployment. Instead of creating separate branches and custom code for individual clients, I adopted a unified approach, allowing simultaneous updates across all containers. This streamlined deployment procedures and enhanced agility in feature delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation and Deployment Pain Points:
&lt;/h3&gt;

&lt;p&gt;The manual update process, involving container shutdowns, code pulls, image rebuilding, and container restarts, proved laborious and prone to downtime. Recognizing the need for automation, I introduced Jenkins into the workflow. By configuring Jenkins to automate deployment tasks, such as pulling code changes and rebuilding containers, I alleviated deployment pains and enabled seamless feature integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Addressing Next.js Caching Challenges:
&lt;/h3&gt;

&lt;p&gt;Next.js caching limitations posed a significant hurdle, particularly in a multi-client environment where data consistency was paramount. Transitioning to a SaaS architecture necessitated a shift in caching strategies, opting for client-side fetching with React Query to mitigate caching issues effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mitigating Gmail SMTP Constraints:
&lt;/h3&gt;

&lt;p&gt;Utilizing Gmail SMTP for email dispatch posed significant challenges due to the imposed daily email quotas. Understanding the critical need for reliable email delivery while staying within these constraints, I engaged in extensive discussions with clients to devise a sustainable solution.&lt;/p&gt;

&lt;p&gt;Collaboratively, we strategized to optimize email dispatch schedules, ensuring emails were sent efficiently while adhering to Gmail's limitations. After thorough deliberation, we agreed to truncate the 24-hour email dispatch window to a more manageable 9 hours, spanning from 7 AM to 4 PM.&lt;/p&gt;

&lt;p&gt;Calculating the optimal email frequency within this timeframe, we settled on a duration of 3 minutes between each email dispatch. This meticulous planning ensured that the total number of emails sent per day per account remained well within Gmail's prescribed limits.&lt;/p&gt;

&lt;p&gt;By implementing this refined scheduling strategy, clients were assured of uninterrupted email delivery to both their internal addresses for verification purposes and their target recipients. This collaborative approach not only addressed the immediate constraint posed by Gmail SMTP limitations but also fostered a deeper understanding of client needs and expectations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolving Next.js Instrumentation and Cron Job Issues:
&lt;/h3&gt;

&lt;p&gt;Technical glitches with Next.js instrumentation and cron job management necessitated a shift in approach. By decoupling cron-related functionalities from Next.js and implementing a separate Express.js server, I successfully resolved these issues and ensured reliable cron job scheduling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing for Efficiency and Scalability:
&lt;/h3&gt;

&lt;p&gt;Further optimizations included migrating the application from VPS to Vercel for cost efficiency and scalability, as well as transitioning the database to Neon DB for enhanced affordability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;Through iterative problem-solving and adaptation, I successfully overcame various challenges in email scheduling, culminating in a robust and efficient solution. This journey underscores the importance of flexibility, automation, and client collaboration in delivering effective software solutions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cron</category>
      <category>nextjs</category>
      <category>vps</category>
    </item>
  </channel>
</rss>
