[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-api-rate-limiting-before-traffic":3,"blog-nav-api-rate-limiting-before-traffic":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},"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.","An API without limits will do whatever a client asks, as often as the client asks. Login, one-time codes, search, and “give me every row” are the routes that get expensive first. Waiting for real traffic to discover that is how you discover it in production.\n\nOWASP’s API Security Top 10 for 2023 lists this as [API4:2023 Unrestricted Resource Consumption](https:\u002F\u002Fowasp.org\u002FAPI-Security\u002Feditions\u002F2023\u002Fen\u002F0xa4-unrestricted-resource-consumption\u002F). The published control includes a limit on how often a client can call the API, a limit on sensitive operations such as OTP and password recovery, and a cap on how many records one response returns. We are citing the 2023 edition. There is not a newer OWASP API list we are pretending exists.\n\n## Where the limits go first\n\n| Route | Why it is first |\n|-------|-----------------|\n| Login, password reset, OTP | Cheap to call, costly when someone automates them |\n| Search and filtered lists | One request can turn into a bad query |\n| Webhook receivers | A retry storm and an attacker look similar |\n| Exports | They read more data than a page view |\n\nA single “1000 requests a minute” that treats a health check like a login is a number, not a design. Anonymous routes key by IP. Authenticated routes key by user. An office NAT is a reason to tune the login limit, not a reason to remove it.\n\n[API-first backends](\u002Fblog\u002Fapi-first-backends-for-mobile) already say rate limiting belongs on the API. [Security basics](\u002Fblog\u002Fsecurity-basics-ph-sme-apps) is passwords, roles, and backups — not this. The [launch checklist](\u002Fblog\u002Flaunch-checklist-ph-web-products) names the control. This article is where we place it.\n\n## What the app should do\n\nLaravel’s throttle middleware is enough for most of the systems we ship. Return a clear 429. Cap page size on list endpoints so a client cannot ask for a million rows because the parameter was trusted. API4 calls that out specifically.\n\nLimits are not a substitute for authorization. A logged-in user who may not export the customer table should get a 403, not a slower 200.\n\n## Straight next step\n\n[Send the public and authenticated routes](\u002Fcontact) if you are about to expose an API beyond your own Nuxt app. We will mark the ones that need a tight limit before launch. We will not sell a separate security product for a middleware change.","Engineering",6,[11,12,13],"API","Security","Laravel","\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",false,true,"2026-10-16T01:00:00.000Z",52,"live","\u002Fblog\u002Fapi-rate-limiting-before-traffic","\u003Cp>An API without limits will do whatever a client asks, as often as the client asks. Login, one-time codes, search, and “give me every row” are the routes that get expensive first. Waiting for real traffic to discover that is how you discover it in production.\u003C\u002Fp>\n\u003Cp>OWASP’s API Security Top 10 for 2023 lists this as \u003Ca href=\"https:\u002F\u002Fowasp.org\u002FAPI-Security\u002Feditions\u002F2023\u002Fen\u002F0xa4-unrestricted-resource-consumption\u002F\" rel=\"noopener noreferrer\">API4:2023 Unrestricted Resource Consumption\u003C\u002Fa>. The published control includes a limit on how often a client can call the API, a limit on sensitive operations such as OTP and password recovery, and a cap on how many records one response returns. We are citing the 2023 edition. There is not a newer OWASP API list we are pretending exists.\u003C\u002Fp>\n\u003Ch2>Where the limits go first\u003C\u002Fh2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Route\u003C\u002Fth>\n\u003Cth>Why it is first\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Login, password reset, OTP\u003C\u002Ftd>\n\u003Ctd>Cheap to call, costly when someone automates them\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Search and filtered lists\u003C\u002Ftd>\n\u003Ctd>One request can turn into a bad query\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Webhook receivers\u003C\u002Ftd>\n\u003Ctd>A retry storm and an attacker look similar\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Exports\u003C\u002Ftd>\n\u003Ctd>They read more data than a page view\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>A single “1000 requests a minute” that treats a health check like a login is a number, not a design. Anonymous routes key by IP. Authenticated routes key by user. An office NAT is a reason to tune the login limit, not a reason to remove it.\u003C\u002Fp>\n\u003Cp>\u003Ca href=\"\u002Fblog\u002Fapi-first-backends-for-mobile\" rel=\"noopener noreferrer\">API-first backends\u003C\u002Fa> already say rate limiting belongs on the API. \u003Ca href=\"\u002Fblog\u002Fsecurity-basics-ph-sme-apps\" rel=\"noopener noreferrer\">Security basics\u003C\u002Fa> is passwords, roles, and backups — not this. The \u003Ca href=\"\u002Fblog\u002Flaunch-checklist-ph-web-products\" rel=\"noopener noreferrer\">launch checklist\u003C\u002Fa> names the control. This article is where we place it.\u003C\u002Fp>\n\u003Ch2>What the app should do\u003C\u002Fh2>\n\u003Cp>Laravel’s throttle middleware is enough for most of the systems we ship. Return a clear 429. Cap page size on list endpoints so a client cannot ask for a million rows because the parameter was trusted. API4 calls that out specifically.\u003C\u002Fp>\n\u003Cp>Limits are not a substitute for authorization. A logged-in user who may not export the customer table should get a 403, not a slower 200.\u003C\u002Fp>\n\u003Ch2>Straight next step\u003C\u002Fh2>\n\u003Cp>\u003Ca href=\"\u002Fcontact\" rel=\"noopener noreferrer\">Send the public and authenticated routes\u003C\u002Fa> if you are about to expose an API beyond your own Nuxt app. We will mark the ones that need a tight limit before launch. We will not sell a separate security product for a middleware change.\u003C\u002Fp>\n",{"prev":28,"next":44,"related":59},{"slug":29,"title":30,"description":31,"category":8,"readTime":9,"tags":32,"coverImage":35,"coverImageAlt":36,"heroImage":37,"heroImageAlt":36,"metaTitle":38,"metaDescription":39,"ogImage":40,"noindex":20,"published":21,"publishAt":41,"sortOrder":42,"updatedAt":41,"status":24,"path":43},"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.",[13,33,34],"Queues","Architecture","\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",{"slug":45,"title":46,"description":47,"category":8,"readTime":9,"tags":48,"coverImage":50,"coverImageAlt":51,"heroImage":52,"heroImageAlt":51,"metaTitle":53,"metaDescription":54,"ogImage":55,"noindex":20,"published":21,"publishAt":56,"sortOrder":57,"updatedAt":56,"status":24,"path":58},"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.",[11,49,13],"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",[60,62,64],{"slug":45,"title":46,"description":47,"category":8,"readTime":9,"tags":61,"coverImage":50,"coverImageAlt":51,"heroImage":52,"heroImageAlt":51,"metaTitle":53,"metaDescription":54,"ogImage":55,"noindex":20,"published":21,"publishAt":56,"sortOrder":57,"updatedAt":56,"status":24,"path":58},[11,49,13],{"slug":29,"title":30,"description":31,"category":8,"readTime":9,"tags":63,"coverImage":35,"coverImageAlt":36,"heroImage":37,"heroImageAlt":36,"metaTitle":38,"metaDescription":39,"ogImage":40,"noindex":20,"published":21,"publishAt":41,"sortOrder":42,"updatedAt":41,"status":24,"path":43},[13,33,34],{"slug":65,"title":66,"description":67,"category":8,"readTime":68,"tags":69,"coverImage":73,"coverImageAlt":74,"heroImage":75,"heroImageAlt":74,"metaTitle":76,"metaDescription":77,"ogImage":78,"noindex":20,"published":21,"publishAt":79,"sortOrder":80,"updatedAt":79,"status":24,"path":81},"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.",7,[70,71,72],"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"]