<?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: Muhammad Waleed Khalil</title>
    <description>The latest articles on DEV Community by Muhammad Waleed Khalil (@mwaleedkhalil).</description>
    <link>https://dev.to/mwaleedkhalil</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%2F4005682%2Ffb56d9b8-e637-4766-90c7-336c735dc97f.jpg</url>
      <title>DEV Community: Muhammad Waleed Khalil</title>
      <link>https://dev.to/mwaleedkhalil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mwaleedkhalil"/>
    <language>en</language>
    <item>
      <title>I built CarvePHP: finding service boundaries in Laravel monoliths</title>
      <dc:creator>Muhammad Waleed Khalil</dc:creator>
      <pubDate>Sat, 27 Jun 2026 18:00:52 +0000</pubDate>
      <link>https://dev.to/mwaleedkhalil/i-built-carvephp-finding-service-boundaries-in-laravel-monoliths-103m</link>
      <guid>https://dev.to/mwaleedkhalil/i-built-carvephp-finding-service-boundaries-in-laravel-monoliths-103m</guid>
      <description>&lt;h2&gt;
  
  
  I built CarvePHP: finding service boundaries in Laravel monoliths
&lt;/h2&gt;

&lt;p&gt;I recently released &lt;strong&gt;CarvePHP v0.1.2-alpha&lt;/strong&gt;, an open-source Laravel package that helps teams analyze large Laravel monoliths and identify possible service boundaries.&lt;/p&gt;

&lt;p&gt;The idea came from a common problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Moving from a monolith to services is not hard because creating a new service is hard.&lt;br&gt;
It is hard because deciding &lt;strong&gt;what to extract&lt;/strong&gt; and &lt;strong&gt;why&lt;/strong&gt; is hard.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most Laravel monoliths grow naturally over time. Routes, controllers, models, migrations, jobs, events, and database tables become connected in ways that are not always obvious from the folder structure.&lt;/p&gt;

&lt;p&gt;CarvePHP tries to make those connections visible.&lt;/p&gt;




&lt;h2&gt;
  
  
  What CarvePHP does
&lt;/h2&gt;

&lt;p&gt;CarvePHP combines &lt;strong&gt;static analysis&lt;/strong&gt; and &lt;strong&gt;runtime tracing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Current alpha features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scans Laravel routes, controllers, models, migrations, and database usage&lt;/li&gt;
&lt;li&gt;optionally traces real runtime route/table coupling&lt;/li&gt;
&lt;li&gt;builds a dependency graph&lt;/li&gt;
&lt;li&gt;suggests candidate service boundaries&lt;/li&gt;
&lt;li&gt;generates Markdown/JSON migration reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not a “one-click microservices” tool.&lt;/p&gt;

&lt;p&gt;That would be misleading.&lt;/p&gt;

&lt;p&gt;The goal is to help developers make safer, more explainable migration decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example workflow
&lt;/h2&gt;

&lt;p&gt;Install it with Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require carvephp/carve:^0.1@alpha &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then 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 artisan carve:install
php artisan carve:doctor
php artisan carve:scan &lt;span class="nt"&gt;--pretty&lt;/span&gt;
php artisan carve:analyze
php artisan carve:boundaries &lt;span class="nt"&gt;--report&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;carve-boundaries.md
php artisan carve:report &lt;span class="nt"&gt;--output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;carve-report.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a migration report showing possible boundaries, related routes/controllers/models/tables, coupling signals, and warnings.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why static analysis is not enough
&lt;/h2&gt;

&lt;p&gt;Static analysis can tell you what the code &lt;em&gt;appears&lt;/em&gt; to depend on.&lt;/p&gt;

&lt;p&gt;But real applications often behave differently at runtime.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one route may touch multiple tables&lt;/li&gt;
&lt;li&gt;two tables may frequently appear together in the same request&lt;/li&gt;
&lt;li&gt;a controller may indirectly depend on a model through a service&lt;/li&gt;
&lt;li&gt;shared tables may make extraction risky&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why CarvePHP supports optional runtime tracing.&lt;/p&gt;

&lt;p&gt;Runtime tracing is disabled by default and is designed to be safe. It does not log request bodies or SQL bindings by default.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example boundary idea
&lt;/h2&gt;

&lt;p&gt;A report might suggest a boundary like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Candidate: Billing

Tables:
- invoices
- payments
- customers

Evidence:
- invoice and payment routes touch related tables
- invoices and payments co-occur in runtime traces
- billing controllers and models are strongly connected

Risk:
- customers table may be shared with other areas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not mean “extract Billing automatically.”&lt;/p&gt;

&lt;p&gt;It means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Here is a possible boundary, and here is the evidence behind it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the kind of information I would want before starting a real migration.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it does not do yet
&lt;/h2&gt;

&lt;p&gt;CarvePHP is still alpha.&lt;/p&gt;

&lt;p&gt;It does not currently provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automatic service extraction&lt;/li&gt;
&lt;li&gt;automatic database splitting&lt;/li&gt;
&lt;li&gt;production-ready migration orchestration&lt;/li&gt;
&lt;li&gt;guaranteed perfect boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are hard problems and should not be hidden behind marketing language.&lt;/p&gt;

&lt;p&gt;For now, CarvePHP is focused on analysis, visibility, and explainable reports.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported versions
&lt;/h2&gt;

&lt;p&gt;Current alpha supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP 8.2+&lt;/li&gt;
&lt;li&gt;Laravel 11, 12, and 13&lt;/li&gt;
&lt;li&gt;Composer 2.x&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Muhammad-Waleed-Khalil/CarvePHP" rel="noopener noreferrer"&gt;https://github.com/Muhammad-Waleed-Khalil/CarvePHP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packagist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packagist.org/packages/carvephp/carve" rel="noopener noreferrer"&gt;https://packagist.org/packages/carvephp/carve&lt;/a&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require carvephp/carve:^0.1@alpha &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Feedback wanted
&lt;/h2&gt;

&lt;p&gt;I am looking for feedback from Laravel/PHP developers who have worked with large monoliths.&lt;/p&gt;

&lt;p&gt;A few questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What evidence would you want before trusting a service boundary suggestion?&lt;/li&gt;
&lt;li&gt;Would graph visualization be useful?&lt;/li&gt;
&lt;li&gt;Should the next release focus more on FormRequest analysis, API Resource analysis, or better reporting?&lt;/li&gt;
&lt;li&gt;What Laravel patterns should the scanner support first?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any feedback, criticism, or real-world edge cases would be appreciated.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>opensource</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
