[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-modular-monolith-vs-microservices":3,"blog-nav-modular-monolith-vs-microservices":27},{"slug":4,"title":5,"description":6,"body":7,"category":8,"readTime":9,"tags":10,"coverImage":14,"coverImageAlt":15,"heroImage":16,"heroImageAlt":15,"metaTitle":17,"metaDescription":18,"ogImage":19,"noindex":20,"published":21,"publishAt":22,"sortOrder":23,"updatedAt":22,"status":24,"path":25,"bodyHtml":26},"modular-monolith-vs-microservices","When a modular monolith is the better system","One Laravel deployable with explicit modules, until a boundary must ship and fail on its own. A shared database plus a network call is not scale.","A second service is a second deploy, a second log, and a network call where a function call used to be. That is worth it when a boundary must ship and fail on its own. It is not worth it because a diagram called the boxes “scalable.”\n\nMartin Fowler’s [Monolith First](https:\u002F\u002Fmartinfowler.com\u002Fbliki\u002FMonolithFirst.html) is still the useful argument: get a well-structured single application running, and split only when you know which boundary hurts. We use that as a design rule, not as a fashion note.\n\n## What we mean by modular\n\nOne Laravel application. Modules with their own folders and their own tables. Bookings does not query billing’s tables because it was faster on a Friday. Notifications does not import a controller from either module. The deployable is still one.\n\n[How we build scalable web applications](\u002Fblog\u002Fhow-we-build-scalable-web-applications) says you can add a module later without demolition. This article is the boundary that makes “later” possible. [Why we model the domain before writing controllers](\u002Fblog\u002Fwhy-we-model-the-domain-before-writing-controllers) is where that line should come from: the domain, not an org-chart slide.\n\n## When a second service is justified\n\nSplit a process out when at least one of these is true:\n\n- A team is actually on call for that part, and it must ship on a different cadence from the rest\n- A workload will knock over the app if it shares a process — a huge export, a noisy integration, a CPU spike you have already seen\n- The boundary has been stable for long enough that you are tired of deploying it with unrelated changes\n\n“We might need scale someday” is not on the list. More clients are not a split either. [API-first backends](\u002Fblog\u002Fapi-first-backends-for-mobile) are still one backend with several faces. A Nuxt site and a phone app do not require two business-logic services.\n\n## What we will not build\n\n- Three services sharing one database, called microservices. You kept the coupling and added the network.\n- A new repository for a feature one person maintains, plus a queue and a cache, because a slide had those icons.\n- A rewrite of a working modular app because a conference talk used Kubernetes.\n\nIf the modules are a mess, fix the boundaries inside the app. A network boundary will not clarify a domain you have not named.\n\n## Straight next step\n\nIf someone has proposed a service per feature, [tell us which workflow would move and who would operate it](\u002Fcontact). If nobody is on call for the second service, the answer is a module, not a platform.","Engineering",7,[11,12,13],"Architecture","Laravel","Modules","\u002Fimages\u002Fjournal\u002Fmodular-monolith-vs-microservices-cover.webp?v=20261013b","Software team working together around laptops","\u002Fimages\u002Fjournal\u002Fmodular-monolith-vs-microservices-hero.webp?v=20261013b","When a Modular Monolith Beats Microservices | PrimeCode","When one deployable Laravel application is the better system, and the few cases that justify a second service.","\u002Fimages\u002Fjournal\u002Fmodular-monolith-vs-microservices-og.webp?v=20261013b",false,true,"2026-10-07T01:00:00.000Z",48,"live","\u002Fblog\u002Fmodular-monolith-vs-microservices","\u003Cp>A second service is a second deploy, a second log, and a network call where a function call used to be. That is worth it when a boundary must ship and fail on its own. It is not worth it because a diagram called the boxes “scalable.”\u003C\u002Fp>\n\u003Cp>Martin Fowler’s \u003Ca href=\"https:\u002F\u002Fmartinfowler.com\u002Fbliki\u002FMonolithFirst.html\" rel=\"noopener noreferrer\">Monolith First\u003C\u002Fa> is still the useful argument: get a well-structured single application running, and split only when you know which boundary hurts. We use that as a design rule, not as a fashion note.\u003C\u002Fp>\n\u003Ch2>What we mean by modular\u003C\u002Fh2>\n\u003Cp>One Laravel application. Modules with their own folders and their own tables. Bookings does not query billing’s tables because it was faster on a Friday. Notifications does not import a controller from either module. The deployable is still one.\u003C\u002Fp>\n\u003Cp>\u003Ca href=\"\u002Fblog\u002Fhow-we-build-scalable-web-applications\" rel=\"noopener noreferrer\">How we build scalable web applications\u003C\u002Fa> says you can add a module later without demolition. This article is the boundary that makes “later” possible. \u003Ca href=\"\u002Fblog\u002Fwhy-we-model-the-domain-before-writing-controllers\" rel=\"noopener noreferrer\">Why we model the domain before writing controllers\u003C\u002Fa> is where that line should come from: the domain, not an org-chart slide.\u003C\u002Fp>\n\u003Ch2>When a second service is justified\u003C\u002Fh2>\n\u003Cp>Split a process out when at least one of these is true:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>A team is actually on call for that part, and it must ship on a different cadence from the rest\u003C\u002Fli>\n\u003Cli>A workload will knock over the app if it shares a process — a huge export, a noisy integration, a CPU spike you have already seen\u003C\u002Fli>\n\u003Cli>The boundary has been stable for long enough that you are tired of deploying it with unrelated changes\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>“We might need scale someday” is not on the list. More clients are not a split either. \u003Ca href=\"\u002Fblog\u002Fapi-first-backends-for-mobile\" rel=\"noopener noreferrer\">API-first backends\u003C\u002Fa> are still one backend with several faces. A Nuxt site and a phone app do not require two business-logic services.\u003C\u002Fp>\n\u003Ch2>What we will not build\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>Three services sharing one database, called microservices. You kept the coupling and added the network.\u003C\u002Fli>\n\u003Cli>A new repository for a feature one person maintains, plus a queue and a cache, because a slide had those icons.\u003C\u002Fli>\n\u003Cli>A rewrite of a working modular app because a conference talk used Kubernetes.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>If the modules are a mess, fix the boundaries inside the app. A network boundary will not clarify a domain you have not named.\u003C\u002Fp>\n\u003Ch2>Straight next step\u003C\u002Fh2>\n\u003Cp>If someone has proposed a service per feature, \u003Ca href=\"\u002Fcontact\" rel=\"noopener noreferrer\">tell us which workflow would move and who would operate it\u003C\u002Fa>. If nobody is on call for the second service, the answer is a module, not a platform.\u003C\u002Fp>\n",{"prev":28,"next":45,"related":62},{"slug":29,"title":30,"description":31,"category":8,"readTime":9,"tags":32,"coverImage":36,"coverImageAlt":37,"heroImage":38,"heroImageAlt":37,"metaTitle":39,"metaDescription":40,"ogImage":41,"noindex":20,"published":21,"publishAt":42,"sortOrder":43,"updatedAt":42,"status":24,"path":44},"nuxt-3-end-of-life-ssr-ssg-hybrid","Nuxt 3 is end of life. Choose a rendering mode on Nuxt 4","Nuxt 3 support ended 31 July 2026. Stay on Nuxt 4, pick static, server, or client per route, and do not ship a Nuxt 5 preview.",[33,34,35],"Nuxt","Rendering","Web","\u002Fimages\u002Fjournal\u002Fnuxt-3-end-of-life-ssr-ssg-hybrid-cover.webp?v=20261013b","HTML and SVG markup on a screen","\u002Fimages\u002Fjournal\u002Fnuxt-3-end-of-life-ssr-ssg-hybrid-hero.webp?v=20261013b","Nuxt 3 Is End of Life. Rendering on Nuxt 4 | PrimeCode","Nuxt 3 support ended 31 July 2026. How to choose SSR, static, or hybrid on Nuxt 4, and why Nuxt 5 is not the October upgrade.","\u002Fimages\u002Fjournal\u002Fnuxt-3-end-of-life-ssr-ssg-hybrid-og.webp?v=20261013b","2026-10-05T01:00:00.000Z",47,"\u002Fblog\u002Fnuxt-3-end-of-life-ssr-ssg-hybrid",{"slug":46,"title":47,"description":48,"category":8,"readTime":9,"tags":49,"coverImage":53,"coverImageAlt":54,"heroImage":55,"heroImageAlt":54,"metaTitle":56,"metaDescription":57,"ogImage":58,"noindex":20,"published":21,"publishAt":59,"sortOrder":60,"updatedAt":59,"status":24,"path":61},"postgresql-vs-mysql-for-applications","PostgreSQL or MySQL: choose for the workload, not the habit","MySQL is enough for ordinary relational apps. PostgreSQL earns its place with overlap rules, JSON you query, and search in the database.",[50,51,52],"PostgreSQL","MySQL","Database","\u002Fimages\u002Fjournal\u002Fpostgresql-vs-mysql-for-applications-cover.webp?v=20261013b","Server racks with network cables in a data room","\u002Fimages\u002Fjournal\u002Fpostgresql-vs-mysql-for-applications-hero.webp?v=20261013b","PostgreSQL vs MySQL for Applications | PrimeCode","How to choose PostgreSQL or MySQL for a business application — constraints, JSON, and search — without a benchmark contest.","\u002Fimages\u002Fjournal\u002Fpostgresql-vs-mysql-for-applications-og.webp?v=20261013b","2026-10-09T01:00:00.000Z",49,"\u002Fblog\u002Fpostgresql-vs-mysql-for-applications",[63,80,95],{"slug":64,"title":65,"description":66,"category":8,"readTime":67,"tags":68,"coverImage":71,"coverImageAlt":72,"heroImage":73,"heroImageAlt":72,"metaTitle":74,"metaDescription":75,"ogImage":76,"noindex":20,"published":21,"publishAt":77,"sortOrder":78,"updatedAt":77,"status":24,"path":79},"idempotency-keys-webhooks-side-effects","Idempotency keys: one webhook, one side effect","Retries are normal. Store the key with the result and enforce it with a unique constraint so a second delivery cannot create a second row.",6,[69,70,12],"API","Webhooks","\u002Fimages\u002Fjournal\u002Fidempotency-keys-webhooks-side-effects-cover.webp?v=20261013b","Person writing on a printed form","\u002Fimages\u002Fjournal\u002Fidempotency-keys-webhooks-side-effects-hero.webp?v=20261013b","Idempotency Keys for Webhooks | PrimeCode","How an API stores an idempotency key so a retried webhook updates one record instead of creating a second side effect.","\u002Fimages\u002Fjournal\u002Fidempotency-keys-webhooks-side-effects-og.webp?v=20261013b","2026-10-19T01:00:00.000Z",53,"\u002Fblog\u002Fidempotency-keys-webhooks-side-effects",{"slug":81,"title":82,"description":83,"category":8,"readTime":67,"tags":84,"coverImage":86,"coverImageAlt":87,"heroImage":88,"heroImageAlt":87,"metaTitle":89,"metaDescription":90,"ogImage":91,"noindex":20,"published":21,"publishAt":92,"sortOrder":93,"updatedAt":92,"status":24,"path":94},"api-rate-limiting-before-traffic","Rate-limit the API before the expensive routes exist","Login, OTP, search, webhooks, and unbounded page size are the routes to limit first. OWASP API4:2023 is the control, not a new security product.",[69,85,12],"Security","\u002Fimages\u002Fjournal\u002Fapi-rate-limiting-before-traffic-cover.webp?v=20261013b","Padlock resting on a laptop keyboard","\u002Fimages\u002Fjournal\u002Fapi-rate-limiting-before-traffic-hero.webp?v=20261013b","Rate-Limit the API Before Traffic Grows | PrimeCode","Where a Laravel API needs rate limits first — login, OTP, search, and webhooks — and what OWASP API4:2023 actually asks for.","\u002Fimages\u002Fjournal\u002Fapi-rate-limiting-before-traffic-og.webp?v=20261013b","2026-10-16T01:00:00.000Z",52,"\u002Fblog\u002Fapi-rate-limiting-before-traffic",{"slug":96,"title":97,"description":98,"category":8,"readTime":67,"tags":99,"coverImage":101,"coverImageAlt":102,"heroImage":103,"heroImageAlt":102,"metaTitle":104,"metaDescription":105,"ogImage":106,"noindex":20,"published":21,"publishAt":107,"sortOrder":108,"updatedAt":107,"status":24,"path":109},"queues-work-outside-the-http-request","Queues: work that does not belong in the HTTP request","The request commits the booking or the order. Mail, PDFs, webhooks, and exports belong on a worker, and that worker must be safe to retry.",[12,100,11],"Queues","\u002Fimages\u002Fjournal\u002Fqueues-work-outside-the-http-request-cover.webp?v=20261013b","Warehouse aisles of packed orders waiting to move","\u002Fimages\u002Fjournal\u002Fqueues-work-outside-the-http-request-hero.webp?v=20261013b","Queues: Work That Leaves the HTTP Request | PrimeCode","Which web-app tasks belong in a Laravel queue — mail, webhooks, exports — and why a timeout is the wrong place to notice.","\u002Fimages\u002Fjournal\u002Fqueues-work-outside-the-http-request-og.webp?v=20261013b","2026-10-14T01:00:00.000Z",51,"\u002Fblog\u002Fqueues-work-outside-the-http-request"]