<?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>Forem: Rafhael Marsigli</title>
    <description>The latest articles on Forem by Rafhael Marsigli (@rmarsigli).</description>
    <link>https://forem.com/rmarsigli</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1999884%2Fddf1f3d8-b1ac-4093-a08b-15b4000a82a9.png</url>
      <title>Forem: Rafhael Marsigli</title>
      <link>https://forem.com/rmarsigli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rmarsigli"/>
    <language>en</language>
    <item>
      <title>SLA, Free Tier, and Professional Maturity</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Wed, 04 Feb 2026 17:06:25 +0000</pubDate>
      <link>https://forem.com/rmarsigli/sla-free-tier-and-professional-maturity-1l2n</link>
      <guid>https://forem.com/rmarsigli/sla-free-tier-and-professional-maturity-1l2n</guid>
      <description>&lt;p&gt;Early in your career, you usually measure the success of a stack by efficiency: “How can I deliver maximum performance while spending the minimum amount of resources?”. It’s an intellectually stimulating challenge. However, as the years go by — and a few production incidents pile up in your baggage — the metric changes.&lt;/p&gt;

&lt;p&gt;Professional maturity doesn’t arrive when you master the framework of the moment, but when you understand that not every technical decision is about performance or cost. Some decisions are purely about &lt;strong&gt;who holds the bag when things go wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every action has a reaction. And every lack of action, a lack of reaction&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Before moving on:&lt;/strong&gt; if you’re setting up a home lab or a study project, ignore all of this. But if there’s a paying client on the other end, things get tight.&lt;/p&gt;

&lt;h2&gt;
  
  
  The common mistake: confusing price with risk
&lt;/h2&gt;

&lt;p&gt;There’s a dangerous confusion in our development “bubble”: the idea that free is inherently bad and paid is necessarily good. That’s not quite how it works. The problem isn’t the value of the invoice at the end of the month, but &lt;strong&gt;where that resource is positioned in your architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The truth is that everything “works until it doesn’t.” A lab accepts anything; production doesn’t. The mistake isn’t using a &lt;em&gt;free&lt;/em&gt; service. The mistake is using a service without guarantees at the heart of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SLA really means
&lt;/h2&gt;

&lt;p&gt;Let’s step outside the books here: if you look up the academic definition of SLA (&lt;em&gt;Service Level Agreement&lt;/em&gt;), you’ll find uptime percentages and availability calculations. But in the real world — real people, flesh and bone, with their own motivations — SLA is something else: &lt;strong&gt;it’s the boundary of responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SLA is the line that divides what is a “vendor technical incident” from what is “a problem exclusively yours”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;With SLA&lt;/strong&gt;: If the service goes down, there is a contract, a response window, and a legal obligation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Without SLA&lt;/strong&gt;: If the service goes down, the provider owes you nothing. And “nothing”, in this case, includes even a support response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without an SLA, you can be “terminated” for any reason, in any situation — how do you explain that to paying clients? At the end of the day, SLA is what separates a professional partnership from silent “good luck.” A service with an SLA usually has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Incident response&lt;/strong&gt; with defined windows&lt;/li&gt;
&lt;li&gt;Priority in &lt;strong&gt;mitigation queues&lt;/strong&gt; during regional failures&lt;/li&gt;
&lt;li&gt;Financial credits or &lt;strong&gt;contractual penalties&lt;/strong&gt; in case of violation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without an SLA, there is no queue, there is no deadline, and there is no obligation — and if it exists, there is no obligation to deliver any of it. You’re not just cheaper in the queue — you’re out of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61w56n821m29ezvsjig4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61w56n821m29ezvsjig4.png" alt="Chose your path!" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Free Tier &lt;em&gt;with&lt;/em&gt; SLA
&lt;/h3&gt;

&lt;p&gt;The entry point starts here.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, I’m not anti-free. On the contrary, many excellent services offer free tiers that are designed for production from day one.&lt;/p&gt;

&lt;p&gt;We’re talking about categories like transactional emails, DNS, basic observability services, or third-party APIs. The characteristic here is clear: limits are explicit, continuity is guaranteed and, if you exceed usage, billing is automatic. The service is free up to a point, but the &lt;strong&gt;support structure and the seriousness of the service are the same as the paid plan&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is an entry strategy, not a shot in the dark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Free Tier &lt;em&gt;without&lt;/em&gt; SLA
&lt;/h3&gt;

&lt;p&gt;Here, if I liked emojis, I’d use the siren and warning ones several times.&lt;/p&gt;

&lt;p&gt;The real problem lives in “free by benevolence”. That model where the provider offers a resource without contractual guarantees. Here, the scenario changes: accounts can be terminated without notice, resources can be removed overnight and, in case of regional instability, you’re last in the priority queue.&lt;/p&gt;

&lt;p&gt;Without an SLA, you’re building your house on rented land and the owner can ask for it back at any moment. If the service disappears, all the downtime and data loss become a problem you’ll have to explain alone to your client.&lt;/p&gt;

&lt;p&gt;Real examples of critical infrastructure interruptions at companies with SLAs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS&lt;/strong&gt;: in October 2025, Amazon Web Services suffered a major outage in its US-EAST-1 region, affecting platforms like Reddit, Snapchat, Uber rival Lyft and many dependent services. The failure started in an internal network subsystem, blocking everything from DNS to core APIs for hours. This type of event shows that even giant providers can impact the core when a central component fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure&lt;/strong&gt;: in October 2025 (that month was rough), Microsoft faced a significant outage in Azure Front Door, impacting critical services like Microsoft 365 (Teams, Outlook, SharePoint) and infrastructure associated with the Azure environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do we learn from this? Even a service with an SLA can suffer interruptions; the difference is that, with an SLA, there is a formal response process and possible compensation — without it, you and your client are left in a void and depend on the provider’s goodwill, while your client is sending that two-minute voice message to your WhatsApp.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core vs. Edge: The distinction that changes the game
&lt;/h2&gt;

&lt;p&gt;To decide where to use what, I use a simple mental model: the division between &lt;strong&gt;Core&lt;/strong&gt; and &lt;strong&gt;Edge&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Core&lt;/strong&gt;: What keeps the system alive. Compute, database, base networking. If this goes down, the system stops existing. In the Core, &lt;em&gt;Free Tier&lt;/em&gt; without SLA is a bet that’s far too dangerous for any serious professional&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Edge&lt;/strong&gt;: Auxiliary services. Integration webhooks, analytics, secondary job triggers or non-critical audit logs. If the edge fails, the impact is contained&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideally, even edge services should have SLAs, even when they’re on a free tier. “Free with automatic billing when you exceed limits” is still a contract. “Free by benevolence” is not. The difference isn’t technical — it’s strategic. &lt;strong&gt;Free in the core is a bet. Free at the edge is a strategy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0r6n812h7shtgw37ww6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0r6n812h7shtgw37ww6.png" alt="No SLA, no guarantee" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The argument nobody likes to hear
&lt;/h2&gt;

&lt;p&gt;Whenever we discuss this, someone raises their hand and says: &lt;em&gt;“But I’ve been using service X for five years and never had a problem.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We need to be honest&lt;/strong&gt;: “never had a problem” is not an engineering metric, it’s a statistic of luck. And luck is not an infrastructure strategy. Seniority begins precisely when you consciously decide to &lt;strong&gt;reduce risk&lt;/strong&gt;, instead of proving you can operate at the edge of danger.&lt;/p&gt;

&lt;p&gt;Personal experience, no matter how long, does not replace a contractual guarantee when disaster knocks on the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  A career decision, not a stack decision
&lt;/h2&gt;

&lt;p&gt;When you work as a freelancer or lead a project, your reputation is on the line. For a personal project, a weekend offline is a lesson. For a client, it’s loss and broken trust — and even lawsuits, depending on the size of the mess.&lt;/p&gt;

&lt;p&gt;Choosing to pay for a service with an SLA — or opting for a free tier that offers minimum guarantees — is a decision about your &lt;strong&gt;quality of sleep and the longevity of your career&lt;/strong&gt;. It’s about predictability. It’s about being the professional the client trusts because they know you’re not “playing” with their business.&lt;/p&gt;

&lt;h2&gt;
  
  
  The criterion I carry for life
&lt;/h2&gt;

&lt;p&gt;Before implementing any service in a production application for a final client, I run a small mental checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does this service have a clear SLA?&lt;/li&gt;
&lt;li&gt;If it goes down right now, who is responsible for responding?&lt;/li&gt;
&lt;li&gt;If it disappears tomorrow, how big is my migration effort?&lt;/li&gt;
&lt;li&gt;Am I saving money or am I just taking on a risk that doesn’t belong to me?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mature engineering isn’t about extracting every drop of performance from the stack or saving every cent. It’s about &lt;strong&gt;knowing where not to play&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>architecture</category>
      <category>freelance</category>
      <category>devops</category>
    </item>
    <item>
      <title>Real-World Core Web Vitals: What Actually Impacts Business</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Sat, 31 Jan 2026 17:17:12 +0000</pubDate>
      <link>https://forem.com/rmarsigli/real-world-core-web-vitals-what-actually-impacts-business-55hn</link>
      <guid>https://forem.com/rmarsigli/real-world-core-web-vitals-what-actually-impacts-business-55hn</guid>
      <description>&lt;p&gt;In a &lt;a href="https://dev.to/rmarsigli/pagespeed-70-vs-95-the-true-reality-3kb0"&gt;previous post&lt;/a&gt;, I've talked about the &lt;strong&gt;real-world PageSpeed reality for typical websites&lt;/strong&gt;. Now it’s time to move past opinion and look at &lt;strong&gt;real companies&lt;/strong&gt;, &lt;strong&gt;real experiments&lt;/strong&gt;, and &lt;strong&gt;measurable business impact&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ve selected &lt;strong&gt;four real, well-documented cases&lt;/strong&gt; where performance and Core Web Vitals improvements produced concrete results, followed by &lt;strong&gt;two broader data points&lt;/strong&gt; that help put everything into perspective — no hype, no miracle promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four cases with real impact
&lt;/h2&gt;

&lt;p&gt;These are not small or isolated cases. They involve &lt;strong&gt;large companies&lt;/strong&gt;, operating in &lt;strong&gt;highly competitive markets&lt;/strong&gt;, spending millions to improve and optimize their code quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vodafone: +8% in sales after improving LCP
&lt;/h3&gt;

&lt;p&gt;Vodafone ran a &lt;strong&gt;&lt;a href="https://web.dev/case-studies/vodafone/" rel="noopener noreferrer"&gt;controlled A/B test&lt;/a&gt;&lt;/strong&gt; comparing two versions of a landing page. The main difference between them was &lt;strong&gt;performance&lt;/strong&gt;, especially &lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt;. After improving LCP by roughly &lt;strong&gt;31%&lt;/strong&gt;, the results were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;+8% increase in sales&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;+15% increase in lead-to-visit rate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;+11% increase in cart-to-visit rate&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the clearest examples of how &lt;strong&gt;performance directly impacts conversion when there is traffic volume and a well-defined funnel&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Search: a direct correlation between speed and abandonment
&lt;/h3&gt;

&lt;p&gt;Google itself has published data showing that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When load time increases from &lt;strong&gt;1s to 3s&lt;/strong&gt;, the probability of bounce increases by &lt;strong&gt;32%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;When it goes from &lt;strong&gt;1s to 5s&lt;/strong&gt;, bounce probability can increase by up to &lt;strong&gt;90%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a ranking case. It’s more important than that: a &lt;strong&gt;&lt;a href="https://blog.google/products/admanager/the-need-for-mobile-speed" rel="noopener noreferrer"&gt;real user behavior signal&lt;/a&gt;&lt;/strong&gt; that directly affects retention, engagement, and conversion metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  T-Mobile: aligning performance metrics with business metrics
&lt;/h3&gt;

&lt;p&gt;T-Mobile &lt;strong&gt;&lt;a href="https://web.dev/case-studies/t-mobile" rel="noopener noreferrer"&gt;implemented monitoring&lt;/a&gt;&lt;/strong&gt; based on &lt;strong&gt;real user data (field data)&lt;/strong&gt; using &lt;code&gt;web-vitals.js&lt;/code&gt;. They found that degradations in metrics such as LCP and CLS were directly associated with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;higher bounce rates
&lt;/li&gt;
&lt;li&gt;lower conversion rates
&lt;/li&gt;
&lt;li&gt;worse perceived user experience
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This case is not about a single headline number. It’s about proving that performance degradations show up directly in &lt;strong&gt;business metrics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon7i3kghhmtqw2xxplz7.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon7i3kghhmtqw2xxplz7.webp" alt="In a close race, Core Web Vitals makes all the difference" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Shopify: where every 100ms matters
&lt;/h3&gt;

&lt;p&gt;Shopify published &lt;strong&gt;&lt;a href="https://shopify.engineering/milliseconds-make-millions" rel="noopener noreferrer"&gt;internal data&lt;/a&gt;&lt;/strong&gt; showing that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;100ms improvements in load time&lt;/strong&gt; resulted in measurable increases in conversion rate&lt;/li&gt;
&lt;li&gt;Small performance regressions caused negative revenue impact at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This type of impact only shows up when traffic operates at massive scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data that puts everything into context
&lt;/h2&gt;

&lt;p&gt;Not every performance improvement shows up as direct conversion. These data points help explain the real role of Core Web Vitals within the ranking ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google: Core Web Vitals are a ranking factor, but not a dominant one
&lt;/h3&gt;

&lt;p&gt;Google &lt;strong&gt;&lt;a href="https://www.searchenginejournal.com/google-core-web-vitals-ranking/430636" rel="noopener noreferrer"&gt;officially states&lt;/a&gt;&lt;/strong&gt; that &lt;strong&gt;Core Web Vitals are part of the ranking signals&lt;/strong&gt;, but &lt;strong&gt;they do not replace relevant content, authority, or satisfied search intent&lt;/strong&gt;. According to John Mueller (Google Search Relations), CWV works more as a &lt;strong&gt;tie-breaker&lt;/strong&gt; than as a primary ranking factor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Studies show many top-ranking sites don’t pass all CWV thresholds
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.perficient.com/insights/research-hub/impact-of-core-web-vitals-on-ranking" rel="noopener noreferrer"&gt;Independent analyses&lt;/a&gt;&lt;/strong&gt; indicate that &lt;strong&gt;many well-ranking pages do not meet all Core Web Vitals thresholds&lt;/strong&gt;, reinforcing that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CWV helps, especially in competitive scenarios, but it does not replace content, authority, or well-served intent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof0qta6u6s9gnvvx16h6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof0qta6u6s9gnvvx16h6.webp" alt="Is your speed impacting your customer?" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So… what does this prove?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance and Core Web Vitals generate real impact&lt;/strong&gt; when there is a technical bottleneck, meaningful traffic volume, and conversion on the table
&lt;/li&gt;
&lt;li&gt;They are part of &lt;strong&gt;modern SEO&lt;/strong&gt;, but they don’t replace content, authority, or intent
&lt;/li&gt;
&lt;li&gt;Improving CWV helps you &lt;strong&gt;compete better&lt;/strong&gt;, not “hack” rankings
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Performance is a leverage point — powerful, but contextual. When there is scale and a real bottleneck, it turns into &lt;strong&gt;revenue&lt;/strong&gt;. Outside of that, it turns into &lt;strong&gt;cost&lt;/strong&gt;. Mature architecture is not about chasing perfect scores — it’s about knowing &lt;strong&gt;when to stop optimizing and start delivering value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before optimizing another 5 points of CWV, validate whether it actually solves a real business problem.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webperf</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Cut Hosting Costs by $250/year With a Simple VPS Setup</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Wed, 28 Jan 2026 19:41:30 +0000</pubDate>
      <link>https://forem.com/rmarsigli/how-i-cut-hosting-costs-by-250year-with-a-simple-vps-setup-15mb</link>
      <guid>https://forem.com/rmarsigli/how-i-cut-hosting-costs-by-250year-with-a-simple-vps-setup-15mb</guid>
      <description>&lt;p&gt;&lt;strong&gt;I'll get straight to the point:&lt;/strong&gt; I maintain 5 legacy web clients. They pay me for simple hosting, and until last month, they were all sitting on a cPanel reseller account that cost me about approx. &lt;strong&gt;$28 USD&lt;/strong&gt; (R$ 160.00/month.&lt;/p&gt;

&lt;p&gt;Today, I migrated everything to a setup that costs me &lt;strong&gt;$7.50 USD&lt;/strong&gt;, and I'm able to deliver a better service.&lt;/p&gt;

&lt;p&gt;These are old, chill, loyal clients who just want the peace of mind of knowing that: their sites will stay online, and their emails will reach suppliers, accountants, etc., without having to hang on the phone with support. Well, that last point can be a real &lt;strong&gt;pain in the neck&lt;/strong&gt; for those using shared hosting—but that's a topic for another discussion.&lt;/p&gt;

&lt;p&gt;The thing is, every end of the year, the provider sends me a price hike notice that gets more absurd every time—I get it, costs are up, but I have nothing to do with that.&lt;/p&gt;

&lt;p&gt;So, before the year ended and my hosting plan expired, I decided to "seek knowledge."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijf28e5fk35g13mce1b6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijf28e5fk35g13mce1b6.webp" alt="The - VPS - truth is out there" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alternative
&lt;/h2&gt;

&lt;p&gt;After a lot (or maybe not so much) of research, the best alternative I found—one that had a good cost for me and delivered equal or better quality for my beloved clients—was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hetzner VPS&lt;/strong&gt; (~$7/month with backups)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HestiaCP&lt;/strong&gt; as my control panel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare&lt;/strong&gt; for DNS (Free plan)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brevo&lt;/strong&gt; for Email (Free plan)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first thing I had to get used to (one of the few downsides) is that Hestia is ugly. &lt;strong&gt;Ugly as sin.&lt;/strong&gt; Not that cPanel is a work of art, but HestiaCP's layout looks like it came straight out of the 90s. Plus, the interface forces you to click three times more (and guess where things are hidden) to get to where cPanel would get you in one click. &lt;strong&gt;Coolify&lt;/strong&gt;, which doesn't even focus that much on beauty, runs circles around poor old HestiaCP visually. But Hestia is that "ugly but functional" tool that gets the job done, and gets it done well.&lt;/p&gt;

&lt;p&gt;Yeah, but for the savings, it was &lt;strong&gt;totally&lt;/strong&gt; worth it. The first step was renting a new Hetzner server (I already have an account with a few servers there, so this was literally just configuration), and—after setting up the Firewall—installing HestiaCP on bare metal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Never install a service like HestiaCP inside a Docker container; &lt;em&gt;stick&lt;/em&gt; it directly onto the machine (bare metal). It was built to manage the OS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even before migrating the (few) clients, I added all of them to Cloudflare to speed up DNS propagation—it was almost instant. Configuring the accounts afterward was easy: first, I "disable the Cloudflare proxy (the orange cloud)" to generate the SSL on the server, and then enable it again later (this avoids that SSL handshake latency between the client in Brazil and the server in Germany).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfy1kel3gb5vh773klnn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfy1kel3gb5vh773klnn.webp" alt="Careful! Wrong choice goes to spam!!" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  And finally, the email configuration
&lt;/h3&gt;

&lt;p&gt;This was supposed to be the part where &lt;strong&gt;"the rubber meets the road"&lt;/strong&gt; (or where the nightmare begins). But it wasn't.&lt;/p&gt;

&lt;p&gt;It would be madness to use the Hetzner IP to send emails directly; it's begging for a headache (blocklists hate cheap cloud IPs). The alternative was using an SMTP Relay: 1. AWS SES, 2. Resend, or 3. Brevo.&lt;/p&gt;

&lt;p&gt;I chose &lt;strong&gt;Brevo&lt;/strong&gt; because I can have more than one domain on the free plan, unlike Resend. Plus, I get 300 free emails per day, which is way above the volume my clients actually use. I also didn't want to go through AWS SES's massive bureaucracy—I wouldn't be surprised if they asked for a &lt;strong&gt;blood sample&lt;/strong&gt; just to unlock a production account.&lt;/p&gt;

&lt;p&gt;Here, I have the peace of mind that even if I need to pay for Brevo's monthly plan in the future, I'll still be turning a profit.&lt;/p&gt;

&lt;p&gt;So, it was just a matter of creating an API key to use in my Hestia setup and watching the logs to see if everything was going smoothly. Honestly? It's easier to configure this than dealing with "graylist" issues and the bad reputation of shared IPs from popular hosting providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result one month later
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero&lt;/strong&gt; client complaints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero&lt;/strong&gt; email deliverability issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fluid&lt;/strong&gt; site navigation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All my fears fell apart. Was it hard work? Yes, because you have to manually configure one client, repeat for the next, repeat for the next... But on the technical side, it's incredibly simple and robust.&lt;/p&gt;

&lt;p&gt;And cheap. Can it be more work? Sure, but the support from those big companies often can't solve anything without you giving them technical hints or begging to be escalated to a higher tier of operations anyway. In the end, it was worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bottom line:&lt;/strong&gt; From R$ 160+ (January would have had another hike) down to approx. R$ 45.00 ($7.50 USD). After this first month, I thought: &lt;em&gt;"Ah... I should have done this years ago, and I'd have a brand new motorcycle in the garage by now! (or not)"&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  About scale
&lt;/h3&gt;

&lt;p&gt;This is not a project meant for dozens of servers. It’s designed to maintain what I already have, with room for ~10 more simple accounts without issues.&lt;/p&gt;

&lt;p&gt;It’s not a huge amount of money saved, but it’s a great way to apply and learn different approaches in production. &lt;strong&gt;Not every client wants extreme performance&lt;/strong&gt; - most of them just want the basics online, &lt;strong&gt;reliably&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra Tip
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cover your back.&lt;/strong&gt; Hosting is wonderful until the first limit is hit or the first IP gets blocked. Have transparent contracts and terms of service, both for you and your clients. Define clear storage limits, fair extra fees if a limit is breached, and explicitly define punitive actions in case of abuse—&lt;em&gt;like spamming, for example&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>devops</category>
      <category>freelance</category>
    </item>
    <item>
      <title>This Post Wasn’t Written by AI</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Mon, 26 Jan 2026 19:30:06 +0000</pubDate>
      <link>https://forem.com/rmarsigli/this-post-wasnt-written-by-ai-3ge1</link>
      <guid>https://forem.com/rmarsigli/this-post-wasnt-written-by-ai-3ge1</guid>
      <description>&lt;p&gt;Or was it? 🤔&lt;/p&gt;

&lt;p&gt;Let’s be honest: just the emoji used here already raises suspicion. This emoji pattern is used to exhaustion by AI-generated texts &lt;em&gt;("please Claude, don’t use emojis in the DAMN REPO DOCUMENTATION")&lt;/em&gt;, so before even reaching the second sentence the reader is already skeptical (and rightly so). I myself start reading with bias, looking for signals instead of ideas — and I use AI for a lot of things.&lt;/p&gt;

&lt;p&gt;Those signals show up fast. The structure is just too good. Balanced paragraphs, a clear introduction, organized development, a predictable conclusion. A text built to perform well: SEO, headings, keywords nicely distributed, and that strategic separation (which annoys me) with &lt;code&gt;---&lt;/code&gt; between &lt;code&gt;h2&lt;/code&gt;s. Because every “well-written” article needs a visual pause.&lt;/p&gt;

&lt;p&gt;And when AI&lt;br&gt;&lt;br&gt;
Creates those texts&lt;br&gt;&lt;br&gt;
That look like a poem?&lt;br&gt;&lt;br&gt;
Full of punchy one-liners??&lt;/p&gt;

&lt;p&gt;Yeah, that’s been bothering me. A lot. Sometimes I just want to read without feeling like I’m being led around by an algorithm or by a clearly manipulative text. Don’t get me wrong, none of this is wrong. But the problem is that, added together, &lt;strong&gt;everything starts to sound the same&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3s8jb5ghpc7gj1u1nn6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3s8jb5ghpc7gj1u1nn6.webp" alt="" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The bad side
&lt;/h2&gt;

&lt;p&gt;When I launched the blog on my site, I fell into this trap — not in the way big news portals do, but in a more “juvenile” way. I’d write the article, AI would improve it, I’d read the result — think it looked beautiful — and publish it. The next day, when I reread it, I felt embarrassed, rewrote it, added my human flaws (which I actually like!). But then it doesn’t engage.&lt;/p&gt;

&lt;p&gt;Writing without AI makes me realize that I love writing, but I’m painfully bad at it. I’ve always dreamed of writing a book, even if it sells nothing, but my very human limitations get in the way of producing something decent. The short-term solution I found is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use AI to tear your text apart, give that &lt;strong&gt;brutally honest&lt;/strong&gt; critique — but without rewriting it. Let me spend half an hour here writing, even if that means publishing one less post per month.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But is it worth it? Probably not. Let’s be real. Look at the most consumed content, the most mainstream stuff, the best-selling books, the most listened-to music, the most watched movies. &lt;strong&gt;This is how the world works&lt;/strong&gt;. And this is where the so-called dead internet theory starts to feel less exaggerated and more like a natural consequence: Skynet won’t take over the internet, we won’t become slaves, babies won’t feed the Matrix — but humans have discovered it’s easier to outsource thinking than to sustain an original idea.&lt;/p&gt;

&lt;p&gt;Thinking is tiring, making mistakes publicly is costly, and having an opinion exposes you — oooh, nice punchy sentence! Like it or not, AI creates a comfortable, error-proof safety layer. We stop exposing what we really think or what our real quality is, and instead expose what we want to show — or what others expect from us.&lt;/p&gt;

&lt;p&gt;As a result, that text about that amazing project becomes 100% technical, beautiful, but empty of business logic — why was that decision made? AI doesn’t know, and it was the one who wrote it. We end up in that space where everything is well written, everything is correct… and everything is the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0aeomi9gyg12rkc27ryf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0aeomi9gyg12rkc27ryf.webp" alt="Modern news websites" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The good side?
&lt;/h2&gt;

&lt;p&gt;There’s a lot of good stuff there — which can &lt;strong&gt;be used for evil&lt;/strong&gt; or just used poorly. I now have: a reviewer, a junior programmer, a DevOps assistant, and hundreds of other roles/tasks just a chat away. Same quality as a real specialist? Of course not. But delivering something decent for a fraction of a fraction of the cost? Absolutely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok, but you’re contributing to the end of jobs, creative work, humanity, the whales.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here I need to bring up a harsh reality: &lt;strong&gt;nobody cares&lt;/strong&gt;. Often not even us. We don’t fight for what we don’t actively defend — we just accept it, or get left behind. Small developers, small studios, and creative people without deep technical backgrounds are now shipping genuinely useful things thanks to the accessibility AI brought. And it feels like this is just the beginning. I don’t even know what my professional future will look like in 10 years, but I have to reference that now-dead blog/podcast I loved: &lt;strong&gt;Update or Die&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’m from the era when DreamWeaver was loved (that’s a lie, that era never existed), and even though I was slow to adopt some things, I realized how rewarding it is to have an assistant on your second monitor working on your side project while you do your day job. Or that AI technical review that will save you — and teach you — a lot before an important presentation.&lt;/p&gt;

&lt;p&gt;It’s dangerously gratifying. Once again, we’re putting ourselves in the hands of a few big companies. So what can we do? Get very rich and escape to the countryside (lovely dream), or accept it and try to build some financial cushion. Maybe the future of content isn’t about proving it was written by humans, but about accepting that &lt;strong&gt;if no one risks saying something real, it hardly matters who wrote it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Damn, I’m really nailing the punchy lines today.&lt;/p&gt;

&lt;p&gt;So tell me — do you think this text was written by AI? Or not? 🤔&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8tks6oj5ebvmiprftns.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8tks6oj5ebvmiprftns.webp" alt="Someone tell him" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>How I Built Persistent Memory for AI Using TypeScript and Markdown</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Fri, 23 Jan 2026 21:35:27 +0000</pubDate>
      <link>https://forem.com/rmarsigli/how-i-built-persistent-memory-for-ai-using-typescript-and-markdown-4pkk</link>
      <guid>https://forem.com/rmarsigli/how-i-built-persistent-memory-for-ai-using-typescript-and-markdown-4pkk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Cross-platform. TypeScript strict mode. 30 E2E tests. Multi-OS CI. Independent technical review. Built in &lt;strong&gt;less than 24 hours&lt;/strong&gt;, with AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the story of the build.&lt;/strong&gt; What happened in the following 30 days is another story.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The pain that woke me up in the morning
&lt;/h2&gt;

&lt;p&gt;If you use Claude, Codex, or any AI assistant for programming, you’ve lived this. Every session starts the same way: paste context, repeat rules, reinforce decisions already made, warn about what cannot be done, explain the project’s patterns one more time. No matter how good the AI is, it always starts from zero.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Ah, but just keep a CLAUDE.md, GEMINI.md, etc.”&lt;/em&gt; Yes, you can do that. But what can a single file really represent in a living project, with history, accumulated decisions, and current state? In the end, it’s like working with an extremely capable developer, but with a &lt;strong&gt;goldfish memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I had already been trying - and managing, with a lot of manual work — to solve this for months using hand-written Markdown. It worked, but it was rough. Every new project felt like starting from scratch, as if I were carving important decisions into stone every time.&lt;/p&gt;

&lt;p&gt;The problem was never the AI. It was the lack of &lt;strong&gt;persistent memory&lt;/strong&gt;, &lt;strong&gt;real history&lt;/strong&gt;, and decisions that don’t get lost between sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea: external memory for AI
&lt;/h2&gt;

&lt;p&gt;After shaping and organizing the ideas in my head for a while, at 8 a.m. I woke up decided — it’s like those days when you wake up possessed by the urge to clean the house — everything was clear enough to turn into code.&lt;/p&gt;

&lt;p&gt;That’s how &lt;strong&gt;AIPIM - AI Project Instruction Manager&lt;/strong&gt; was born. It used to be AI Project Manager, then AIPM, then… through a random but valuable insight, AIPIM. Not as hype, but as a practical tool. &lt;strong&gt;The proposal is simple:&lt;/strong&gt; create an external memory layer between the project and the AI assistant.&lt;/p&gt;

&lt;p&gt;This layer solves two core pains: keeping persistent context between sessions and recording the real project history, including decisions, tasks, and current state. All of this is organized in a &lt;code&gt;.project/&lt;/code&gt; structure, entirely in Markdown, which the AI can read, respect, and follow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;context.md&lt;/code&gt; becomes the source of truth&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;current-task.md&lt;/code&gt; defines the focus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decisions/&lt;/code&gt; stores immutable architectural decisions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backlog/&lt;/code&gt; with &lt;code&gt;completed/&lt;/code&gt; records work honestly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was already using exactly this methodology before AIPIM existed. The difference is that now it became an &lt;strong&gt;automated CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I worked with AI (for real)
&lt;/h2&gt;

&lt;p&gt;I didn’t use passive autocomplete. I used &lt;strong&gt;Claude Code&lt;/strong&gt; as a pair programmer. I defined the direction, the AI executed, I reviewed everything, fixed a lot of things, and nothing passed without full understanding. There was no “accept suggestion.” There was technical dialogue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A real example:&lt;/strong&gt; I asked for a framework detector. The AI proposed heuristics using &lt;code&gt;package.json&lt;/code&gt; and the filesystem. I pointed out edge cases, like React with Vite versus CRA, and demanded hierarchical fallback. The flow was continuous, no context switching, always with human decisions in command.&lt;/p&gt;

&lt;h2&gt;
  
  
  By the afternoon, the first &lt;code&gt;aipim install&lt;/code&gt; worked
&lt;/h2&gt;

&lt;p&gt;Near the end of the afternoon, the first milestone was standing: a functional CLI. It wasn’t magic. There were bugs, tweaks (my goodness, many of them — if Claude had ears, they’d be hurting), and review. AI leaves traces, especially in complex tasks, and someone needs to follow those traces carefully. From the start, I made it clear that the project needed to be cross-platform, with real error handling like &lt;code&gt;EACCES&lt;/code&gt; and &lt;code&gt;ENOSPC&lt;/code&gt;, working on Windows, macOS, and Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates without overwriting customization
&lt;/h2&gt;

&lt;p&gt;This was a point where AI alone wouldn’t solve it. The problem was updating base templates without destroying user customizations. The obvious suggestion was to use &lt;code&gt;git diff&lt;/code&gt;. My answer was simple: what if there’s no git? What if the repository is dirty?&lt;/p&gt;

&lt;p&gt;The solution was architectural. Each generated file receives a cryptographic SHA-256 signature embedded as a comment. If the hash matches, the file is pristine and can be updated. If it diverges, it was modified and must be preserved. Claude implemented it perfectly, but the decision was human. This point, by the way, was one of the most praised in the technical review, compared to strategies used in Kubernetes manifests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests: where AI really shined
&lt;/h2&gt;

&lt;p&gt;I don’t like writing tests &lt;em&gt;(although I do write them)&lt;/em&gt;, and here the AI was absurdly good. I asked for unit tests for the detector and, in minutes, there were 17 cases covering all frameworks. Then I asked for more: 30 cross-platform E2E scenarios. Tests came for installation, update, validation, and task lifecycle, running on Linux, Windows, and macOS in CI. That would have been days of manual work.&lt;/p&gt;

&lt;p&gt;It took just a few hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;TypeScript Strict&lt;/code&gt;, no compromises
&lt;/h2&gt;

&lt;p&gt;Here I was picky, but I’d be with myself anyway. Strict mode, zero &lt;code&gt;any&lt;/code&gt;. The rule was explicit and the AI respected it. In the technical review, the type safety score was 95/100.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brutal and Honest Feedback
&lt;/h2&gt;

&lt;p&gt;The strengths were clear: clean architecture, the SHA-256 signature system, 30 cross-platform E2E scenarios, and strict TypeScript. The red flags were fair too: a &lt;code&gt;diff&lt;/code&gt; command announced but not implemented, a dependency installed and not used, and too few tests in the updater, a critical module.&lt;/p&gt;

&lt;p&gt;The final score was 88/100.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxtyui6n9oyeww6e58nm.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxtyui6n9oyeww6e58nm.webp" alt="Basic flow of using AIPIM" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned in These First 24 Hours
&lt;/h2&gt;

&lt;p&gt;AI doesn’t replace judgment; it executes. Tests stopped being an excuse; in 2026, not having tests is a choice. And speed doesn’t have to kill quality when there’s process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Numbers, 24 Hours Later
&lt;/h2&gt;

&lt;p&gt;There were about 2,000 lines of core code and 2,000 lines of tests, 30 E2E scenarios, strict TypeScript without &lt;code&gt;any&lt;/code&gt;. Without AI, this would have taken one to two weeks. With AI, it took about 24 real hours — including a trip to the mall with my family in the middle of the day. The project was functional, tested, and published to npm. Exactly as I wanted: an evolved version of my old Jurassic Markdown manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Came Next
&lt;/h2&gt;

&lt;p&gt;In the following days, I used AIPIM to manage AIPIM itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I documented nine sessions&lt;/li&gt;
&lt;li&gt;Completed 31 tasks&lt;/li&gt;
&lt;li&gt;Wrote eight ADRs&lt;/li&gt;
&lt;li&gt;Fixed all 16 red flags&lt;/li&gt;
&lt;li&gt;Raised the score from 88 to 90&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But that’s for a next post, because this one has already crossed the healthy longform limit (even though I enjoy it).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbswjb427zo238jrb68y8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbswjb427zo238jrb68y8.webp" alt="Installing AIPIM in your project" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  For Those Who Want to Go Further
&lt;/h2&gt;

&lt;p&gt;The complete technical report is available in the &lt;a href="https://github.com/rmarsigli/aipim/blob/main/.project/reports/first-code-quality-report-2026-01-08.md" rel="noopener noreferrer"&gt;repository&lt;/a&gt;, generated with Claude Code (Sonnet 4.5), and can be read in full. AIPIM is already on &lt;a href="https://npmjs.com/aipim" rel="noopener noreferrer"&gt;npm&lt;/a&gt; and on &lt;a href="https://github.com/rmarsigli/aipim" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Usage is simple and explained in the &lt;code&gt;README&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>showdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>PageSpeed 70 vs 95: the true reality</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Mon, 19 Jan 2026 17:52:05 +0000</pubDate>
      <link>https://forem.com/rmarsigli/pagespeed-70-vs-95-the-true-reality-3kb0</link>
      <guid>https://forem.com/rmarsigli/pagespeed-70-vs-95-the-true-reality-3kb0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Let’s be honest from the start:&lt;/strong&gt; if you have a website for an accounting firm, a psychologist, a real estate agency, a barbershop, a clinic, an office, or any other common local business, it’s very unlikely that someone is opening your site with a stopwatch in hand thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Wow, it loaded in 1.8s instead of 1.2s.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s simply not how most decisions are made in the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  The myth the dev bubble helped create
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(And at some point, I was part of it too.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inside the developer bubble, it often feels like a PageSpeed score below 90 is a serious mistake, Lighthouse not fully green is a sign of negligence, and a CLS above 0.1 is almost an architectural sin. But outside that bubble — where businesses need to generate leads and pay bills — the logic tends to be far more pragmatic.&lt;/p&gt;

&lt;p&gt;Clients want to show up on Google, be found on Maps, inspire trust, and be able to contact someone without friction. They don’t know what LCP is, they don’t care about TBT (not the old Twitter one, the other), and they’re very unlikely to reject a service because a PageSpeed score is 78 instead of 95.&lt;/p&gt;

&lt;p&gt;And that doesn’t make them wrong — just human.&lt;/p&gt;

&lt;h2&gt;
  
  
  So… does PageSpeed matter?
&lt;/h2&gt;

&lt;p&gt;Yes, it does. A lot. But &lt;strong&gt;not in the same way for every context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There’s a massive difference between a &lt;em&gt;truly slow&lt;/em&gt; website — heavy, janky, taking 5, 6, 8 seconds to show anything — and a &lt;em&gt;well-built&lt;/em&gt; site sitting around a 65–80 score, loading fast enough to deliver a solid experience.&lt;/p&gt;

&lt;p&gt;Beyond that point, gains still exist, but they stop being transformational and become incremental. Going from 40 to 70 completely changes user perception. Going from 70 to 95 improves important details, but rarely redefines the outcome of a local business on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  “But what about SEO?”
&lt;/h2&gt;

&lt;p&gt;Yes, speed is a ranking factor. That’s a fact. But it’s also &lt;strong&gt;not the dominant factor&lt;/strong&gt; in most scenarios.&lt;/p&gt;

&lt;p&gt;In practice — especially for common websites — content quality, well-executed local SEO, clarity of the offer, authority, and reviews carry far more weight. Speed works as a strong reinforcement — often as a tie-breaker — but rarely as a miracle solution on its own.&lt;/p&gt;

&lt;p&gt;A PageSpeed score of 98 helps, improves experience, and reduces friction. It just doesn’t compensate for weak content or a confusing value proposition.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point almost no one puts on the table
&lt;/h2&gt;

&lt;p&gt;Chasing very high scores usually involves real technical decisions: reducing animations, revisiting aesthetics, changing rendering strategies, moving to SSG/ISR, optimizing builds, reviewing dependencies. All of that has a cost — in time, complexity, and architectural trade-offs.&lt;/p&gt;

&lt;p&gt;For many common websites, the most visible return from these optimizations appears when there is volume: meaningful traffic, many sessions, many conversions, or more complex digital products. Outside of that, the gains exist, but they’re more subtle and cumulative.&lt;/p&gt;

&lt;p&gt;This isn’t being anti-performance. It’s understanding &lt;strong&gt;technical proportion&lt;/strong&gt;. Architecture is also about knowing how far it makes sense to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmxetgq2cw1os2zoecbx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmxetgq2cw1os2zoecbx.png" alt="Pick your side!" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The right question isn’t “what’s the score?”
&lt;/h2&gt;

&lt;p&gt;The right question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Does my site load fast enough to deliver a good experience and not push people away?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is yes, you’ve already solved most of the problem. Everything else becomes refinement.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick preview of the next post
&lt;/h2&gt;

&lt;p&gt;Before anyone assumes this is just opinion, a future post will continue this discussion and dive into the data: &lt;strong&gt;real studies&lt;/strong&gt;, Core Web Vitals, field metrics, large companies, and concrete impacts on conversion and business. No empty lab tests — just numbers from people who actually gained or lost money because of performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now I want to hear from you:&lt;/strong&gt; have you ever seen a client complain about speed? Lost a project because of a score? Felt a real difference after improving performance?&lt;/p&gt;

&lt;p&gt;Let’s talk about real life — with less dogma and more context.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;This post was conceived, developed, and written by me. I used AI only to improve clarity and readability.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>performance</category>
      <category>webdev</category>
      <category>webperf</category>
    </item>
    <item>
      <title>So, AI will finally take your job</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Wed, 14 Jan 2026 15:00:00 +0000</pubDate>
      <link>https://forem.com/rmarsigli/so-ai-will-finally-take-your-job-e0f</link>
      <guid>https://forem.com/rmarsigli/so-ai-will-finally-take-your-job-e0f</guid>
      <description>&lt;p&gt;This question show up every year wearing a different outfit.&lt;/p&gt;

&lt;p&gt;Before, it was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-code&lt;/li&gt;
&lt;li&gt;No-code&lt;/li&gt;
&lt;li&gt;Dheap offshore labor&lt;/li&gt;
&lt;li&gt;Frameworks that “do everything”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it’s &lt;strong&gt;AI&lt;/strong&gt;’s turn.&lt;/p&gt;

&lt;p&gt;And as always, the fear isn’t irrational — it’s just &lt;strong&gt;misdirected&lt;/strong&gt;. I won’t be a denier, nor an alarmist. This is a practical analysis, based on what’s already happening right now, not on marketing promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistake starts when we confuse code with work
&lt;/h2&gt;

&lt;p&gt;Many people think a programmer’s job is &lt;strong&gt;writing code&lt;/strong&gt;. It’s not. Code is a &lt;strong&gt;byproduct&lt;/strong&gt;. The real work of a programmer is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding problems&lt;/li&gt;
&lt;li&gt;Translating business rules&lt;/li&gt;
&lt;li&gt;Making technical decisions&lt;/li&gt;
&lt;li&gt;Dealing with trade-offs&lt;/li&gt;
&lt;li&gt;Taking responsibility for failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI writes code. It &lt;strong&gt;does not take responsibility for consequences&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI already does better than many people
&lt;/h2&gt;

&lt;p&gt;Let’s be fair. Today, AI is already excellent at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating CRUDs&lt;/li&gt;
&lt;li&gt;Writing repetitive code&lt;/li&gt;
&lt;li&gt;Creating basic tests &lt;del&gt;(oh, thank you AI!)&lt;/del&gt;
&lt;/li&gt;
&lt;li&gt;Refactoring isolated snippets&lt;/li&gt;
&lt;li&gt;Suggesting implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This scares those who live only at this level. And here comes the uncomfortable part:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"a large portion of the market lives exactly there."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Who is actually at risk
&lt;/h2&gt;

&lt;p&gt;AI doesn’t replace “programmers". It replaces &lt;strong&gt;profiles&lt;/strong&gt;. From this perspective, those at risk are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;People who only execute tickets&lt;/li&gt;
&lt;li&gt;Those who copy and paste without understanding&lt;/li&gt;
&lt;li&gt;Those who depend on frameworks to think&lt;/li&gt;
&lt;li&gt;Those who &lt;strong&gt;cannot explain their own code&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These people aren’t losing ground to AI. They’re losing ground to &lt;strong&gt;inevitable automation&lt;/strong&gt;. And being brutally honest, fighting the “AI revolution” is like fighting the industrial revolution — it doesn’t work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who gains strength with AI
&lt;/h2&gt;

&lt;p&gt;Now the other half of the story — and this is where it gets interesting. Gaining strength are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers who understand the domain&lt;/li&gt;
&lt;li&gt;Architects&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Eeal&lt;/del&gt; seniors&lt;/li&gt;
&lt;li&gt;People who know how to say “no”&lt;/li&gt;
&lt;li&gt;those who design before they code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these profiles, AI becomes a force multiplier, not a competitor. In practice, a high-quality employee who doesn’t ask for equity.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI still doesn’t build systems — it builds answers
&lt;/h2&gt;

&lt;p&gt;A point almost no one talks about: AI responds to &lt;strong&gt;prompts&lt;/strong&gt;. It doesn’t understand organizational context. It doesn’t know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why a rule exists&lt;/li&gt;
&lt;li&gt;What level of risk is acceptable&lt;/li&gt;
&lt;li&gt;What would break the business&lt;/li&gt;
&lt;li&gt;who pays the price when things go wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Systems live inside &lt;strong&gt;human realities&lt;/strong&gt;. AI does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The near future: fewer devs, more responsibility?
&lt;/h2&gt;

&lt;p&gt;Yes, there will be fewer positions for trivial code, mechanical tasks, and context-free maintenance. But there will be more demand for clarity, predictability, architecture, and technical communication.&lt;/p&gt;

&lt;p&gt;The market doesn’t want less software. It wants &lt;strong&gt;less chaos&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real dividing line
&lt;/h2&gt;

&lt;p&gt;The question isn’t: “Will AI take my job?” It’s: “Can I explain why my code exists?” If the answer is yes, you’re safe. If it’s no… the problem isn’t AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to prepare (for real)
&lt;/h2&gt;

&lt;p&gt;Not by learning more frameworks.&lt;/p&gt;

&lt;p&gt;But by learning fundamentals, business domain, code reading, clear writing, and simple design. And by using AI as an assistant, a copilot, an accelerator — never as an outsourced brain.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI doesn’t replace professionals
&lt;/h2&gt;

&lt;p&gt;It replaces improvisation, superficiality, and blind dependency. If you write code without understanding the system — yes, your job is at risk. If you build systems that people and businesses depend on — AI came to help you, not replace you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The future doesn’t belong to those who type faster. It belongs to those who &lt;strong&gt;think better&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>developer</category>
    </item>
    <item>
      <title>A Love-Hate Letter do Json</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Wed, 14 Jan 2026 14:43:57 +0000</pubDate>
      <link>https://forem.com/rmarsigli/a-love-hate-letter-do-json-2cmh</link>
      <guid>https://forem.com/rmarsigli/a-love-hate-letter-do-json-2cmh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Using JSON as a configuration format is (usually) a mistake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not a preference. Not a style choice. A normalized architectural mistake, and a very normalized one.&lt;/p&gt;

&lt;p&gt;People get uncomfortable with that sentence because JSON works. And in tech, once something works, we collectively agree to stop asking if it actually makes sense, and we start building religions around it.&lt;/p&gt;

&lt;p&gt;Let’s be clear, JSON is a massive success. As a transport format, it’s basically unbeatable: predictable, deterministic, boring in the best way, trivial to parse, trivial to generate, everywhere. Machine-to-machine, JSON is fantastic. The problem starts when we look at a format designed to be produced by computers, and decide it should also be written, read, reviewed, versioned, and maintained by humans, as if we were also computers, just slower.&lt;/p&gt;

&lt;p&gt;We are not.&lt;/p&gt;

&lt;p&gt;And yes, “but my editor formats it” is not an argument. That’s like saying a chair made of nails is fine because you bought good pants.&lt;/p&gt;

&lt;p&gt;This is not an attack on JSON. This is an attack on the industry habit of using the right tool in the wrong place, then acting surprised when the people writing it start to hate their lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JSON won
&lt;/h2&gt;

&lt;p&gt;JSON didn’t win because it’s expressive. It won because it’s limited, consistent, and boring. That’s an enormous advantage when two systems that don’t know each other need to exchange data without negotiating intent, context, and interpretation.&lt;/p&gt;

&lt;p&gt;It’s a small closed format. No clever shortcuts. No “oh but in this case”. No magical semantics. Just primitives and structure. That is exactly what you want for contracts. When someone says “my API speaks JSON”, everyone understands the shape of the deal instantly. No surprises. No creative interpretations. No YAML-level philosophical debates about what &lt;code&gt;on&lt;/code&gt; means.&lt;/p&gt;

&lt;p&gt;As a transport format, JSON deserves all the respect it gets. If the file is machine-generated, rarely touched, and validated by a strict schema, JSON on disk is fine. My problem is human-authored JSON pretending to be a friendly authoring format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7cd7urfegl67dox8qgs.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7cd7urfegl67dox8qgs.webp" alt="Do not feed the troll" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where everything starts to go wrong
&lt;/h2&gt;

&lt;p&gt;The moment you decide humans should author JSON, you are effectively saying: “the syntax matters more than the intent”. You don’t say it out loud, but that’s the outcome.&lt;/p&gt;

&lt;p&gt;This usually doesn’t come from malice. It comes from laziness dressed up as simplicity: “the system consumes JSON, so people should write JSON”. It sounds logical. It’s also the kind of logic that produces self-inflicted pain at scale.&lt;/p&gt;

&lt;p&gt;JSON demands perfect syntactic precision to express even the smallest idea. One missing quote, one comma, one bracket, and everything breaks. There is no “kind of broken”. There is only “parse error” and the conversation is over.&lt;/p&gt;

&lt;p&gt;For machines, that’s fine. For humans, that’s hostile.&lt;/p&gt;

&lt;p&gt;And before someone says “skill issue”, go edit a large IAM policy JSON at 2am, push it, break production, and then come back to lecture everyone about how “it’s simple, actually”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqphwrtnfg7gnhz3adal3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqphwrtnfg7gnhz3adal3.webp" alt="Do not forget the GODDAMN COMMA!" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON is structurally hostile to humans
&lt;/h2&gt;

&lt;p&gt;This isn’t taste. It’s structural.&lt;/p&gt;

&lt;p&gt;JSON has no comments. JSON is verbose. JSON makes you repeat yourself. JSON makes you care about commas and quotes more than meaning. JSON has no way to express intent, only structure. So people start inventing conventions and superstitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“this key is optional, but only in this scenario”&lt;/li&gt;
&lt;li&gt;“this value is a string, but it behaves like an enum, except when it doesn’t”&lt;/li&gt;
&lt;li&gt;“this section is deprecated, but still required because reasons”&lt;/li&gt;
&lt;li&gt;“don’t touch this block unless you like pain”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because JSON can’t carry context, the context leaks elsewhere: README files, Confluence pages, Slack messages, tribal knowledge, “ask João”. Your configuration stops being configuration and becomes a scavenger hunt.&lt;/p&gt;

&lt;p&gt;When you see a big hand-written JSON file, it rarely communicates clarity. It communicates resistance. It communicates that someone suffered, and the only reason it still exists is because everyone agreed to pretend this is normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON configuration is a normalized mistake
&lt;/h2&gt;

&lt;p&gt;Configuration, by definition, is something humans will read, write, review, version, and argue about in pull requests. It carries intent. It needs context. It benefits from comments. JSON provides none of that, by design.&lt;/p&gt;

&lt;p&gt;So what happens? We create these beautiful 300-line objects full of tiny flags, where one comma can invalidate the entire thing, and then we ship the “documentation” somewhere else. Review becomes painful. Change becomes scary. And the final experience is basically “it works, but it works powered by spite”.&lt;/p&gt;

&lt;p&gt;Examples everyone knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tsconfig.json&lt;/code&gt;: it’s not the worst offender, but it’s the perfect illustration of “human-authored JSON that wants comments really badly”.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt;: scripts, tool configs, overrides, it becomes a dumping ground because it’s convenient, not because it’s good.&lt;/li&gt;
&lt;li&gt;Any complex policy config (permissions, rules, routing, workflows): JSON turns your domain into punctuation management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yes, you can add tooling. You can add schemas. You can add validators. You can add prettier. You can add a UI that generates JSON. Notice something? The more serious your system gets, the more you move humans away from writing JSON. That’s not a coincidence. That’s your own architecture admitting the truth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3admft8olho29ll0zml.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3admft8olho29ll0zml.webp" alt="The good side" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pro-JSON argument
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“But JSON is simple. Everyone knows it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everyone knows a lot of things that are terrible tools for certain jobs.&lt;/p&gt;

&lt;p&gt;Everyone knows regular expressions too. That does not mean we should store business logic as regex strings inside a JSON file and call it “configuration”. Familiarity is not a tool-selection criterion. Fitness for the problem is.&lt;/p&gt;

&lt;p&gt;JSON is simple to consume, not simple to author. And that distinction matters a lot more than people want to admit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authoring formats exist for a reason
&lt;/h2&gt;

&lt;p&gt;If the config is meant to be written by humans, use a format designed for humans.&lt;/p&gt;

&lt;p&gt;TOML exists for a reason. HCL exists for a reason. Even YAML exists for a reason, and yes, YAML has its own problems, and anyone pretending YAML is “clean” has probably never debugged a weird parsing edge case on a Friday night.&lt;/p&gt;

&lt;p&gt;But the point stands: authoring formats usually allow comments, are more readable, and reduce the cognitive cost of writing. They let people think about the domain first, and the representation second.&lt;/p&gt;

&lt;p&gt;Also, a lot of “good” systems already follow this pattern:&lt;/p&gt;

&lt;p&gt;Humans write something expressive. Machines validate and normalize it. JSON only shows up at the boundaries, when data needs to travel, or when it becomes a strict contract between systems.&lt;/p&gt;

&lt;p&gt;That separation is not bureaucracy. It’s respect for human limits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F159osmmhwddu6ddu8iz6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F159osmmhwddu6ddu8iz6.webp" alt="Well... Still better than legacy approaches" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline that avoids unnecessary suffering
&lt;/h2&gt;

&lt;p&gt;In well-designed systems, the flow is usually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Humans author something expressive, comfortable, and reviewable.&lt;/li&gt;
&lt;li&gt;The machine validates it, transforms it, normalizes it.&lt;/li&gt;
&lt;li&gt;JSON appears only when it must: transport, persistence, interop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want typed configuration, TypeScript can be amazing, because types and tooling actually work in your favor.&lt;br&gt;
If you want “configuration people can read and discuss”, TOML/YAML/HCL or a small DSL is often a better fit.&lt;br&gt;
If you want system-to-system contracts, JSON is still the king.&lt;/p&gt;

&lt;p&gt;The pattern repeats in modern tools because it works. It respects human limitations and exploits machine strengths. Forcing JSON from the start skips the sane pipeline and pushes all the cost onto the people who should pay it the least.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ek8uej16uw28rnn0m3r.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ek8uej16uw28rnn0m3r.webp" alt="The Json Cult" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hater or fan?
&lt;/h2&gt;

&lt;p&gt;I still love JSON where it makes sense: contracts, APIs, serialization, machine-to-machine communication.&lt;/p&gt;

&lt;p&gt;I still hate JSON when someone expects me to write, review, and maintain complex rules in it, as if that were a normal human experience.&lt;/p&gt;

&lt;p&gt;This is not elitism. It’s not a trend. It’s not stubbornness.&lt;/p&gt;

&lt;p&gt;It is basic respect for the people who have to deal with the code.&lt;/p&gt;

&lt;p&gt;JSON does not need to be omnipresent to remain valuable. It just needs to stay in the right place.&lt;/p&gt;

&lt;p&gt;And that place is definitely not between you and the keyboard at two in the morning.&lt;/p&gt;

</description>
      <category>json</category>
      <category>programming</category>
      <category>architecture</category>
      <category>api</category>
    </item>
    <item>
      <title>The Silent Revolution of Workflow Automation: How n8n Broke the Market</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Tue, 13 Jan 2026 15:00:00 +0000</pubDate>
      <link>https://forem.com/rmarsigli/the-silent-revolution-of-workflow-automation-how-n8n-broke-the-market-3oep</link>
      <guid>https://forem.com/rmarsigli/the-silent-revolution-of-workflow-automation-how-n8n-broke-the-market-3oep</guid>
      <description>&lt;p&gt;The silent revolution of workflow automation has finally reached everyone's hands. For over a decade, automating processes between different systems was a privilege of large corporations with generous budgets or depended on tools that charged heavily for every small action executed.&lt;/p&gt;

&lt;p&gt;Then came &lt;strong&gt;n8n&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An open-source platform created in Berlin that, in less than six years, has earned over &lt;strong&gt;163,000&lt;/strong&gt; GitHub stars, surpassed &lt;strong&gt;230,000&lt;/strong&gt; active users, and reached a valuation of &lt;strong&gt;$2.5 billion&lt;/strong&gt; in October 2025. More important than the numbers: n8n proved that it was possible to build powerful automations without spending a fortune or handing over data control to third parties.&lt;/p&gt;

&lt;p&gt;This article provides a deep dive into how workflow automation has evolved, why traditional tools created artificial barriers, and how n8n shattered those paradigms. This is a dense, long article backed by extensive research—so get ready and sit back, because there’s quite a story to tell! So grab your snack and drink...&lt;/p&gt;

&lt;h2&gt;
  
  
  The World Before n8n: A Decade of Automation for the Few
&lt;/h2&gt;

&lt;p&gt;To understand n8n's impact, we must first examine the landscape that existed before its arrival. The history of workflow automation for non-programmers began in 2010, when the idea of connecting applications without writing code seemed revolutionary.&lt;/p&gt;

&lt;h2&gt;
  
  
  IFTTT and the Birth of Simple Automation
&lt;/h2&gt;

&lt;p&gt;In December 2010, Linden Tibbets and his brother Alexander launched &lt;strong&gt;IFTTT (If This Then That)&lt;/strong&gt; in San Francisco. The proposal was elegant in its simplicity: create automatic "recipes" based on single triggers. If it rains, send a notification. If you post on Instagram, save the photo to Dropbox.&lt;/p&gt;

&lt;p&gt;The platform quickly won over millions of users—reaching 32 million—but its fundamental architecture imposed severe limitations. IFTTT worked only with single-step linear flows. There was no way to create conditional branches, loops, or complex data transformations. When the company implemented a freemium model in September 2020, limiting free users to just three applets, the community reacted with frustration. The tool that promised simplicity revealed its structural limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zapier and the Consolidation of the Task-Based Model
&lt;/h2&gt;

&lt;p&gt;A year after IFTTT, in October 2011, three freelance developers—Wade Foster, Bryan Helmig, and Mike Knoop—noticed they were building the same integrations repeatedly for different clients. From this frustration, Zapier was born, eventually becoming the giant of the category.&lt;/p&gt;

&lt;p&gt;Zapier grew impressively, reaching &lt;strong&gt;$310 million in annual recurring&lt;/strong&gt; revenue in 2023 and a $5 billion valuation in 2021. However, Zapier's pricing model created a fundamental problem. The platform charges by tasks—and every action within a workflow counts as a separate task. A flow with 10 steps processing 200 orders a day consumes 60,000 monthly tasks, which can easily exceed $899 per month. For startups, costs scale exponentially.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integromat and Make
&lt;/h2&gt;

&lt;p&gt;In Prague, a team led by Ondřej Gazda developed Integromat, launching in 2016. It stood out by offering a more sophisticated visual builder. In 2022, it was rebranded as Make, positioning itself as the enterprise version of Zapier. While it brought innovation, it maintained a pricing model based on operations, where even "polling" (checking for triggers) could consume credits, leading to billing surprises.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xzep1nefihmgg3p3x9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xzep1nefihmgg3p3x9m.png" alt="The World before n8n" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Barriers That Prevented Democratization
&lt;/h2&gt;

&lt;p&gt;Before n8n, four structural obstacles kept workflow automation as a privilege of the few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pricing That Punishes Growth:&lt;/strong&gt; The task-based model created a perverse trap: the more you automated, the more expensive it became.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud-Only and Zero Data Control:&lt;/strong&gt; Data—including access tokens and customer info—flowed through third-party servers, creating security and compliance (GDPR/HIPAA) nightmares.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor Lock-in:&lt;/strong&gt; Workflows built on one platform couldn't be exported to another. If a vendor raised prices, the cost of switching was rebuilding everything from scratch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers Treated as Second-Class Citizens:&lt;/strong&gt; Existing tools offered limited snippets for JavaScript or Python with severe memory and time restrictions, no debugging, and no Git versioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Birth of n8n in Berlin
&lt;/h2&gt;

&lt;p&gt;Enter Jan Oberhauser, a German developer with a unique background in the Hollywood visual effects (VFX) industry. Having worked on films like Maleficent, Jan became an expert in automating pipelines to ensure files flowed seamlessly between artists and renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Personal Frustration to Side Project
&lt;/h2&gt;

&lt;p&gt;When Jan founded his own startups, he found existing automation tools unsatisfactory. He developed n8n as a side project for a year and a half because he needed something that worked with obscure APIs, allowed self-hosting for data protection, and provided access to the source code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Launch
&lt;/h3&gt;

&lt;p&gt;n8n GmbH was founded in June 2019 in Berlin. The name "n8n" is a numeronym for "nodemation"—combining "node" (referring to both the visual interface and Node.js) with "automation."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun Fact: Jan chose the abbreviation because he didn't want to type a long name into the terminal every time he ran a command.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Did n8n Do Differently?
&lt;/h2&gt;

&lt;p&gt;n8n reimagined the fundamental rules of the market through four key architectural decisions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Fair-Code Model
&lt;/h3&gt;

&lt;p&gt;Instead of traditional open-source or closed proprietary models, n8n adopted Fair-Code. The code is on GitHub for everyone to see and modify. It is free for internal use and self-hosting, while protecting the project from being repackaged and sold by hosting competitors.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Free and Unlimited Self-Hosting
&lt;/h3&gt;

&lt;p&gt;This was the most disruptive move: anyone can run n8n on their own infrastructure for free with unlimited executions. A $5-10/month VPS is enough to start. Sensitive data never leaves your infrastructure, making GDPR compliance trivial.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Pricing per Execution, Not per Task
&lt;/h3&gt;

&lt;p&gt;n8n charges (in its cloud version) per workflow execution, not per individual action. A 50-step workflow counts as one execution. This makes n8n &lt;strong&gt;10 to 50 times cheaper&lt;/strong&gt; for complex, high-volume workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Total Freedom for Code
&lt;/h3&gt;

&lt;p&gt;n8n treats developers as first-class citizens. You can write full JavaScript or Python, import any npm library, execute terminal commands, and use native GraphQL. The visual editor allows real-time debugging, showing inputs and outputs for every node.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Market Impact and the AI Era
&lt;/h2&gt;

&lt;p&gt;The combination of these features removed the barriers for millions. Startups can now automate from Day 1. I, Personally, spend &lt;em&gt;less than $ 6 USD) per month&lt;/em&gt; to run my entire n8n infrastructure!&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Catalyst
&lt;/h2&gt;

&lt;p&gt;Since 2022, n8n has positioned itself as the ideal platform for &lt;strong&gt;AI Orchestration&lt;/strong&gt;. It offers over 70 nodes related to &lt;strong&gt;LangChain&lt;/strong&gt;, with native connectors for ChatGPT, Claude, Gemini, and local models via Ollama.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;75% of n8n clients already use AI features&lt;/strong&gt;. Because of self-hosting, companies can build AI agents that handle sensitive data without sending it to a third-party cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now, automation Finally Belongs to Everyone
&lt;/h2&gt;

&lt;p&gt;For over a decade, business automation required a choice between expensive simplicity or inaccessible power. n8n broke that false dichotomy.&lt;/p&gt;

&lt;p&gt;From a side project in Berlin to a $2.5 billion unicorn, n8n's success validates an alternative business model where transparency is the expectation, not the exception. It has forced giants like Zapier and Make to reconsider their pricing and value propositions.&lt;/p&gt;

&lt;p&gt;The future of productivity is about doing less of what doesn't matter to do more of what does. &lt;strong&gt;n8n is the tool for that future&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why I Dropped Laravel Observers?</title>
      <dc:creator>Rafhael Marsigli</dc:creator>
      <pubDate>Mon, 12 Jan 2026 22:30:00 +0000</pubDate>
      <link>https://forem.com/rmarsigli/why-i-divorced-laravel-observers-4j9l</link>
      <guid>https://forem.com/rmarsigli/why-i-divorced-laravel-observers-4j9l</guid>
      <description>&lt;p&gt;In &lt;a href="https://www.rafhael.pro/blog/why-i-dropped-laravel-form-requests-and-laravel-api-resources" rel="noopener noreferrer"&gt;a previous post&lt;/a&gt; about migrating to DTOs, I talked about how I stopped depending on Laravel’s “magic arrays” in favor of stricter typing. That was Step 1 of my journey toward more predictable code. This wasn’t yesterday, and it’s not exactly recent, but I still think it’s worth documenting this experience here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Once you start using DTOs and an &lt;code&gt;Actions/&lt;/code&gt; style architecture, the Observer path becomes weird (and kind of unviable) pretty quickly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, without further ado (yes, I know, I write a lot and I tend to ramble), today I need to talk about Step 2, and this one hurt more than I expected: &lt;strong&gt;I stopped using Observers&lt;/strong&gt; as a crutch.&lt;/p&gt;

&lt;p&gt;For years I was (I mean, I still am, just differently) a Laravel power user. If the docs had a feature, I tried it. Observers felt like a superpower: skinny controllers, “clean” models, and every side effect neatly hidden inside a &lt;code&gt;UserObserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But as my projects stopped being simple CRUD apps and became actual business domains, I started noticing a very ugly pattern: Observers are not clean code. Observers are invisible logic. And invisible logic is the kind of thing that makes you waste an entire afternoon staring at the wrong file, convinced the bug is “in Laravel”, when it’s actually inside an Observer someone created 9 months ago and forgot about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “clean code” illusion
&lt;/h2&gt;

&lt;p&gt;The appeal of an Observer is obvious. You open the controller and it looks beautiful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserData&lt;/span&gt; &lt;span class="nv"&gt;$userData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Look how "clean" this is!&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userData&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty. But there’s a catch: that “clean” is mostly makeup.&lt;/p&gt;

&lt;p&gt;Because, without the developer who will read this file 6 months from now realizing it, that single line &lt;code&gt;User::create()&lt;/code&gt; may trigger a whole chain reaction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sends a welcome email&lt;/li&gt;
&lt;li&gt;Creates a Stripe Customer&lt;/li&gt;
&lt;li&gt;Logs activity&lt;/li&gt;
&lt;li&gt;Notifies a Slack channel&lt;/li&gt;
&lt;li&gt;Updates a search index&lt;/li&gt;
&lt;li&gt;Clears some cache keys&lt;/li&gt;
&lt;li&gt;Brews coffee&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;And that’s where the fun begins. You look at the line, it just “creates a user”. But the system is basically throwing a secret party behind your back.&lt;/p&gt;

&lt;p&gt;This is what I call &lt;strong&gt;Spooky Action at a Distance&lt;/strong&gt;: you change the database here, and code executes somewhere else you didn’t even remember existed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5xeefqcviboalt9lqdv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5xeefqcviboalt9lqdv.webp" alt="Poor Observer! Treat her well, please" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The execution order trap
&lt;/h2&gt;

&lt;p&gt;Another very common issue is execution order betraying you.&lt;/p&gt;

&lt;p&gt;Imagine you have logic in the &lt;code&gt;created&lt;/code&gt; event that depends on some relationship. But if you use &lt;code&gt;User::create()&lt;/code&gt;, &lt;code&gt;created&lt;/code&gt; fires immediately. Often before you had a chance to associate stuff like &lt;code&gt;Roles&lt;/code&gt;, &lt;code&gt;Teams&lt;/code&gt;, &lt;code&gt;Profile&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;And then you start seeing code smells like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Trying to guess if the relation is loaded yet...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;relationLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'team'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fragile. And worse, it’s fragile in a silent way.&lt;/p&gt;

&lt;p&gt;Today it works. Tomorrow someone changes a flow, runs an import, uses &lt;code&gt;createQuietly&lt;/code&gt;, or just changes the order of an &lt;code&gt;attach&lt;/code&gt;, and suddenly your Observer becomes roulette.&lt;/p&gt;

&lt;p&gt;If a business rule depends on the accidental execution order of Eloquent events, that’s not “architecture”. That’s faith.&lt;/p&gt;

&lt;h3&gt;
  
  
  The real issue: side effects with no owner
&lt;/h3&gt;

&lt;p&gt;Deep down, what made me quit wasn’t “observers are evil”. It was realizing I was putting business rules in a place where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s not obvious they exist&lt;/li&gt;
&lt;li&gt;It’s not obvious when they run&lt;/li&gt;
&lt;li&gt;It’s not obvious how to disable them&lt;/li&gt;
&lt;li&gt;It’s not obvious how to test the flow without triggering half the system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when nothing breaks, the mental cost is still there. And when something breaks, the developer debugging it pays the bill.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There’s a moment in every experienced dev’s life where the last thing they want is more headache. They want &lt;strong&gt;control&lt;/strong&gt; and &lt;strong&gt;predictability&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figmfi9de3eom7tdn2dda.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figmfi9de3eom7tdn2dda.webp" alt="The right choice for the right business" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: explicit beats implicit
&lt;/h2&gt;

&lt;p&gt;In the same way I replaced Form Requests with DTOs to make input explicit, I replaced &lt;code&gt;Observers&lt;/code&gt; with explicit &lt;code&gt;Services&lt;/code&gt; and &lt;code&gt;Actions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Yes, it means writing a few more lines.&lt;/p&gt;

&lt;p&gt;But those extra lines tell a story. And story is what your “future self” needs when something goes wrong.&lt;/p&gt;

&lt;p&gt;And I think this is the most important point: an Action wants to be an explicit flow. An Observer wants to be an invisible side effect. Put the two together and you get a system where nobody knows what the “source of truth” for behavior actually is.&lt;/p&gt;

&lt;p&gt;Here’s a refactored version of the flow. Notice there’s no magic. You read the code and you know what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserAction&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;BillingService&lt;/span&gt; &lt;span class="nv"&gt;$billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserData&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

                      &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;afterCommit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                          &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;billing&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WelcomeNotification&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;afterCommit&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bonus is that your code becomes a control panel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want an import to NOT send emails? &lt;strong&gt;Don’t call it&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Want an admin flow that creates users without Stripe? &lt;strong&gt;Don’t call it&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Want to test only “create user” without triggering the rest of the universe? &lt;strong&gt;You can&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Observers ARE acceptable
&lt;/h2&gt;

&lt;p&gt;Does this mean Observers are useless? Obviously not. I still use Observers when it’s a purely technical concern, always true, regardless of context, and not really a business rule.&lt;/p&gt;

&lt;p&gt;Examples I consider acceptable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating a UUID for a model&lt;/li&gt;
&lt;li&gt;Clearing cache keys&lt;/li&gt;
&lt;li&gt;Updating search indexes (Elasticsearch/Meilisearch), depending on the case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But business logic (sending emails, charging a card, assigning teams, provisioning resources)? I avoid it.&lt;/p&gt;

&lt;p&gt;Because business rules need an owner, and they need to live somewhere you can actually see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax97xn6z5fotk7ncisz5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax97xn6z5fotk7ncisz5.webp" alt="Predictability = Free Spirit" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Maturity is predictability
&lt;/h2&gt;

&lt;p&gt;I already hinted at this earlier: when we’re junior, we love tools that do things for us. We love magic.&lt;/p&gt;

&lt;p&gt;As we get more senior (more grumpy?), magic starts charging interest. You start preferring code that says exactly what will happen, even if it looks &lt;strong&gt;less elegant&lt;/strong&gt;. Dropping Observers felt uncomfortable at first. I felt like I was writing “boilerplate”. But that “boilerplate” turned into something much more useful: living documentation. It’s code I can read, understand, and debug without needing a mental map of the entire event system.&lt;/p&gt;

&lt;p&gt;If you’re tired of side effects breaking flows, take a careful look at your Observers.&lt;/p&gt;

&lt;p&gt;Especially the &lt;code&gt;created&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;Especially the one that “just does a tiny thing”.&lt;/p&gt;

&lt;p&gt;And if it makes sense, move it into a &lt;code&gt;Service&lt;/code&gt; or an &lt;code&gt;Action&lt;/code&gt; and make the flow explicit.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>architecture</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
