# Muhammet Şafak > Personal brand site of Muhammet Şafak — polyglot developer and system architect. The portfolio of an engineer building software since 2008, and a development journal spanning from 2014 to today. The blog is a hands-on development journal: posts on PHP, Laravel, JavaScript, TypeScript, Go and web development that reflect a developer’s growth over the years, plus reflections on the software career. The site also lists open-source projects and professional résumé information. In-depth content on software architecture and system design lives on the author’s other site, sade.dev. Türkçe sürüm / Turkish version: https://www.muhammetsafak.com.tr/llms.txt ## Site - [Home](https://www.muhammetsafak.com.tr/en/) - [About](https://www.muhammetsafak.com.tr/en/about/): Who Muhammet Şafak is and what he does. - [Blog](https://www.muhammetsafak.com.tr/en/blog/): All blog posts. - [Portfolio](https://www.muhammetsafak.com.tr/en/portfolio/): Projects. - [Expertise](https://www.muhammetsafak.com.tr/en/expertise/): What I do in each ecosystem, and the evidence. - [Labs](https://www.muhammetsafak.com.tr/en/labs/): Work on its way to a product across the development focus areas; each record states what it does today, its form, maturity and state. - [Research](https://www.muhammetsafak.com.tr/en/research/): Measurements, analyses, surveys and reviews; every record states its method, environment and the date it is valid for. - [Just Ask](https://www.muhammetsafak.com.tr/en/just-ask/): Questions from visitors, answered one by one. - [Résumé](https://www.muhammetsafak.com.tr/en/resume/): Experience, education and skills. - [Contact](https://www.muhammetsafak.com.tr/en/contact/) A plain Markdown version of every post, question, Labs/Research record and project is available by appending `.md` to its URL — for example https://www.muhammetsafak.com.tr/en/blog/is-php-dead-2026-the-data.md ## Projects This whole section as plain Markdown: https://www.muhammetsafak.com.tr/en/portfolio.md - [Parantaj: personal and business finance platform](https://www.muhammetsafak.com.tr/en/portfolio/parantaj/) [ongoing]: Income-expense tracking, budget planning and multi-account management on web, iOS and Android — all three fed by one API. — Role: Owner — Class: SaaS Product — Stack: PHP, Laravel, Go, PostgreSQL, Redis, RabbitMQ, Expo, React Native, Vite, iOS, Android — Started: 2024-10-18 - [BabelQueue: a language-agnostic queue standard](https://www.muhammetsafak.com.tr/en/portfolio/babelqueue/) [ongoing]: A frozen JSON envelope that lets PHP, Python, Go and Node.js share one queue without serialization lock-in. Runs on Redis and RabbitMQ. — Role: Founder & Developer — Class: Flagship — Stack: JSON, Redis, RabbitMQ, PHP, Python, Go, Node.js, Java, .NET — Started: 2026-06-15 - [CommitBrief: local LLM code review CLI](https://www.muhammetsafak.com.tr/en/portfolio/commitbrief/) [ongoing]: A provider-agnostic Go CLI that reviews git diffs without leaving the terminal or leaking the diff: Anthropic, OpenAI, Gemini, Ollama. — Role: Founder & Developer — Class: Flagship — Stack: Go, Cobra, go-git, Anthropic Claude, OpenAI, Google Gemini, Ollama, YAML, Goreleaser, Astro, Tailwind CSS — Started: 2026-04-07 - [InitPHP: 30+ modular PHP libraries](https://www.muhammetsafak.com.tr/en/portfolio/initphp/) [ongoing]: 30+ modular PHP packages — Router, Database, Cache, Mailer, Socket — plus the minimalist MVC framework Framework3, MIT-licensed on Packagist. — Role: Founder & Developer — Class: Older / Hobby Project — Stack: Composer, Git, PHPUnit, PHP — Started: 2022-08-12 - [SignalLock: Bluetooth proximity lock](https://www.muhammetsafak.com.tr/en/portfolio/signallock/) [ongoing]: A privacy-focused menu bar app that locks your computer when you walk away, using a Bluetooth device you already carry. — Role: Owner — Class: Older / Hobby Project — Stack: Swift, SwiftUI, CoreBluetooth, CoreLocation, C#, .NET 8, WinForms — Started: 2026-05-20 - [Looplio: recurring maintenance automation](https://www.muhammetsafak.com.tr/en/portfolio/looplio/) [ongoing]: Turns repeating tasks, maintenance and checks into reusable templates and auto-generated checklists. Web, iOS and Android. — Role: Owner — Class: SaaS Product — Stack: PHP, Laravel, Go, PostgreSQL, Redis, Expo, React Native, iOS, Android — Started: 2026-05-01 - [sakinkal: evidence-based crisis preparedness](https://www.muhammetsafak.com.tr/en/portfolio/sakinkal/) [ongoing]: An offline-accessible, ad-free resource that strips crisis readiness in Turkey of fear and hype. 'No panic, just preparedness.' — Role: Founder & Editor — Class: Publication — Stack: Astro, Tailwind CSS, TypeScript, Markdown, Pagefind, Cloudflare Pages — Started: 2026-05-30 - [TB1MSK: amateur radio station and blog](https://www.muhammetsafak.com.tr/en/portfolio/tb1msk/) [ongoing]: My amateur radio station based in Çatalca/İstanbul (KN41ff): FM, repeaters and APRS on VHF/UHF, plus Turkish writing on emergency comms. — Role: Operator & Developer — Class: Publication — Stack: Astro, TypeScript, Markdown, Cloudflare Pages — Started: 2026-03-20 - [Erkekse: an online magazine for men](https://www.muhammetsafak.com.tr/en/portfolio/erkekse/) [completed]: A subscription-based online magazine on fashion, style, grooming and health, which I published on WordPress between 2016 and 2022. — Role: Founder — Class: Publication — Stack: PHP, WordPress, MariaDB, Linux — Started: 2016-07-20 — Ended: 2022-12-30 ## Expertise — Ecosystems - [PHP Developer](https://www.muhammetsafak.com.tr/en/expertise/php/): A PHP developer since 2008 — work shipped on Laravel, Symfony and CodeIgniter, framework-free libraries, and how I actually pick a framework. - [Backend Developer](https://www.muhammetsafak.com.tr/en/expertise/backend/): What I do behind the API — contracts first, delivery guarantees that queues do not give you, and index decisions made by measurement. - [Go Developer](https://www.muhammetsafak.com.tr/en/expertise/go/): What I build in Go — microservices, queue consumers, HTTP APIs and command-line tools, and why I pick Go for that kind of work. - [JavaScript Developer](https://www.muhammetsafak.com.tr/en/expertise/javascript/): Feeding web and mobile from one API — React Native apps in the stores, contracts carried by TypeScript, and a toolchain that keeps changing. - [Python Developer](https://www.muhammetsafak.com.tr/en/expertise/python/): Where I use Python and where I do not — scripting, data wrangling, tooling, and the claims I decline to make. ## Labs — Development The whole section as plain Markdown: https://www.muhammetsafak.com.tr/en/labs.md - **AI-assisted development** — Where the LLM enters the development loop: code review, static analysis mixed with models, deterministic filters instead of prompts. - **Distributed systems & messaging** — Queues, outbox, idempotent consumption and language-agnostic message contracts. - **Developer tooling & CI** — CLIs, architecture boundaries enforced at build time, automation that measures code health. - **Education & research** — Platforms that make knowledge teachable and researchable: sequenced curricula, source texts, locale-aware full-text search and assessment. - **Automation & data pipelines** — Scheduled jobs, integration pipelines and operational data flows. - **Security & verifiability** — Making events the server cannot observe directly — physical proximity, client-computed results — provable. - **Community & platform** — Splitting a community without forum sprawl: topic-specific clubs, a shared data model, web and mobile moving in parallel. - [academia.sh: can theory and a real field problem live in the same lesson?](https://www.muhammetsafak.com.tr/en/labs/academia/) [in development]: A free, publicly open, text-first learning platform that holds textbook theory and problems actually met in the industry inside a single lesson flow. — What it does today: Live as a free learning platform with no signup wall: the field–curriculum–course–unit–lesson hierarchy, full-text search, progress tracking and verifiable certificates all work. Anyone who wants to read the computer-science curriculum can use it today. — Form: web app — Maturity: beta — Focus: Education & research - [Qurandia: matching two datasets whose numbers disagree, by fingerprinting the text](https://www.muhammetsafak.com.tr/en/labs/qurandia/) [in development]: An open, free resource for reading, understanding and learning the Qur'an, gathering Qur'an- and hadith-centred research under one roof. — What it does today: Live as a free, open resource for reading and searching the Qur'an and hadith side by side; letter-level fingerprint matching gives 91–99% coverage across the hadith collections. Readers and researchers who want to go straight to the source can use it today. — Form: web app — Maturity: alpha — Focus: Education & research - [Swipenor: if the client computes the score, what does the server trust?](https://www.muhammetsafak.com.tr/en/labs/swipenor/) [in development]: A swipe-based true/false trivia game; the real subject is not the game but making a client-computed score verifiable through a signature. — What it does today: The swipe-based true/false quiz runs end to end in its core loop as a mobile app; the score is produced on the client but verified server-side with a server_nonce and an HMAC signature. swipenor.com is the app's landing page, not the game itself. — Form: mobile app — Maturity: beta — Focus: Security & verifiability - [Garajdaş: model-specific community without the forum sprawl](https://www.muhammetsafak.com.tr/en/labs/garajdas/) [in development]: A Reddit-like community platform where every vehicle make and model has its own club, holding ICE and EV under one roof; web and mobile run in parallel. — What it does today: A community platform where every car make and model has its own club; identity, content, notifications and moderation all run on a single-schema API, with the web and mobile clients sharing that one schema. Anyone looking for a community specific to their car's model can join today. — Form: web app, mobile app — Maturity: beta — Focus: Community & platform - [SentryFixer: reading a Sentry error against the code and drafting the fix](https://www.muhammetsafak.com.tr/en/labs/sentryfixer/) [stable]: A Claude Code skill that reads a Sentry issue against the working tree and proposes a fix as a diff and a regression test, touching no file until approved. — What it does today: Reads a Sentry issue against the working tree, produces a root-cause analysis and a fix plan, and touches no file without explicit approval. Anyone using Claude Code who needs to triage a production error can install the skill. — Form: open source — Maturity: release candidate — Focus: AI-assisted development - [Devrazzi: filtering developer news through layers of models](https://www.muhammetsafak.com.tr/en/labs/devrazzi/) [stable]: A content pipeline that screens software and AI news locally with Ollama, hands survivors to larger models, and publishes Turkish and English syntheses. — What it does today: Filters software and AI news through a local Ollama pass and hands the upper layers to the larger models, then writes and publishes the TR/EN synthesis on its own; the web and App Store builds are live. Anyone who wants their daily developer news in one feed can read it. — Form: web app, mobile app — Maturity: release candidate — Focus: Automation & data pipelines - [Two languages sharing one queue without the serialization lock-in](https://www.muhammetsafak.com.tr/en/labs/babelqueue-lab/) [became a product]: A frozen JSON envelope in place of language-specific serialization; it became BabelQueue, a polyglot queue standard. — What it does today: The frozen JSON envelope has four languages — PHP, Python, Go, Node.js — reading the same bytes, with no sidecar and no broker plugin. Teams running a polyglot queue can pick up the spec and the SDKs today. — Form: open source — Focus: Distributed systems & messaging - [Screen lock by Bluetooth proximity: present/absent is not enough](https://www.muhammetsafak.com.tr/en/labs/signallock-lab/) [became a product]: A proximity lock that locks the machine when the device in your pocket walks away; it became the SignalLock menu bar app. — What it does today: Locks the macOS screen when the device you carry moves away; the call rests on a proximity assessment rather than a raw present/absent signal, so fluctuation no longer produces false locks. The menu-bar app is published and ready to install. — Form: open source — Focus: Security & verifiability - [Local code review without letting the diff leave the machine](https://www.muhammetsafak.com.tr/en/labs/commitbrief-lab/) [became a product]: A provider-agnostic Go CLI that has a model review my diff without the diff leaving the machine; it became CommitBrief. — What it does today: Reviews code locally, with the diff never leaving the machine; the `Provider` interface lets Anthropic, OpenAI, Gemini and Ollama plug into one contract. Signed binaries are published — anyone who does not want to hand their diff to a cloud provider can install it. — Form: open source — Focus: AI-assisted development - [Personal and business finance on one data model](https://www.muhammetsafak.com.tr/en/labs/parantaj-lab/) [became a product]: A finance core that keeps multi-account income and expense tracking in a single model; it became Parantaj, running on web, iOS and Android. — What it does today: One account/transaction model carries multi-account management, budgeting, goals and reporting on a single core; the web, iOS and Android clients are all live. Anyone who wants personal and business finances tracked in one place can use it. — Form: open source, web app, mobile app — Focus: Automation & data pipelines - [PHP packages that stand alone and still work together](https://www.muhammetsafak.com.tr/en/labs/initphp-lab/) [became a product]: Modular PHP libraries that work without being tied to a framework; they became the 39-package InitPHP ecosystem and Framework3. — What it does today: A family of 39 PHP packages — Router, Database, Cache, Mailer, Socket and the rest — each usable standalone or together, all shipped through Composer/Packagist under MIT. Any PHP developer who wants the pieces without buying into a framework can install them today. — Form: open source — Focus: Developer tooling & CI ## Research — Records The whole section as plain Markdown: https://www.muhammetsafak.com.tr/en/research.md - **Language & runtime** — What version upgrades, compiler and runtime settings change on the same workload: JIT, opcache, GC and memory behaviour. Release-note and RFC analysis belongs here alongside the measurements. - **Database & queries** — What index strategy, query plans and connection handling cost once the data volume is real. Schema-decision and migration-order analysis belongs here alongside the measurements. - **Service & load** — Latency distribution, saturation point and queue behaviour of a service under load — p95/p99, not the mean. Analysis of patterns like backpressure, circuit breakers and queuing belongs here alongside the measurements. - **Tooling comparison** — The measurable difference between two tools doing the same job: build time, output size, memory and the developer loop. Ecosystem surveys — maintenance health, release cadence, community size — belong here alongside the measurements. - **Frontend performance** — Shipped JS, first paint and interaction delay: how many kilobytes a convenience costs the visitor. Browser-support and API-stability analysis belongs here alongside the measurements. - **Cost & resources** — The side of a decision that reaches the invoice: CPU hours, bandwidth, storage and true cost per request. Pricing-model analysis belongs here alongside the measurements. - [Laravel's preload curve: 123 files buy eight times what the last 1,912 do](https://www.muhammetsafak.com.tr/en/research/laravel-preload-curve/): How far can a curated preload take Laravel, and what does each slice cost in start-up time? — Kind: Measurement — Finding: The curve is not proportional to volume. The first 1,592 files — Laravel's own framework — buy 30 ms and add 1.2 seconds to start-up. The next 1,094 Symfony files buy 9.5 ms for free. The **123 files** after that (psr, carbon) buy 15.7 ms, more than the 1,094 before them. And the last 1,912 buy 1.8 ms while adding another 1.2 seconds. So the blanket preload the earlier record measured as a ceiling is the worst point on the curve that is not the origin: stopping at 2,809 files gives 12.77 ms for 1,514 ms of start-up, while 4,721 files ask 2,691 ms to reach 10.96 ms. — Metrics: Sweet spot: 2,809 files: 12.77 ms (−81%) · Its start-up cost: +1,132 ms · What the 123-file slice buys: 15.7 ms · What the last 1,912 buy: 1.8 ms — Method: The same images, the same PHP 8.4 build and the same measurement point as the opcache record — the first request a container ever serves. Curation is a **path filter** over Composer's classmap rather than a hand-picked list of classes: a hand-picked list cannot be reproduced, a filter can. The five variants nest deliberately (framework ⊂ +symfony ⊂ +psr/carbon ⊂ everything) so the curve reads as "add this much more" rather than as four unrelated points. Fresh container per variant, three repeats, median. Preload runs in php-fpm's master process, so its cost is measured as the time until the container answers with a 200; that window includes nginx's own start-up but is the same constant across all five variants. — Confidence: High confidence — Measured on: 2026-08-22 — Language & runtime - [A partial index makes a queue table forty-one times smaller — for as long as the planner picks it](https://www.muhammetsafak.com.tr/en/research/partial-index-queue-table/): On a Postgres queue table with millions of dead rows, what does a partial index buy, and when does the planner refuse to use it? — Kind: Measurement — Finding: At 10 million dead rows a partial index sustains 11,537 claims per second where the same table without one manages 7. Against a composite index the throughput difference is small (6.9%) but the size difference is not: 7.6 MB against 310.4 MB, and the partial one does not grow with the table because it indexes only the 5,000 live rows. None of that is the real finding. The moment the planner switches a prepared statement to a generic plan the partial index stops being used at all — 11,752 tps becomes 7, and 0.68 ms becomes 1.1 seconds. A factor of 1,673. The composite index is untouched under the same conditions. — Metrics: Partial index, 10M dead rows: 11,537 tps · Same table, no index: 7 tps · Index size, partial / composite: 7.6 / 310.4 MB · Once the plan goes generic: 11,752 → 7 tps (−1,673×) — Method: Postgres 17, one container, explicit settings (shared_buffers 1 GB, work_mem 64 MB, autovacuum on — turning it off would make the numbers prettier and the answer wrong). The `jobs` table holds a constant live set of 5,000 `pending` rows at every tier; the dead set is 100k, 1M and 10M. Each size is seeded once into a **template database** and copied per run: re-seeding per strategy would take longer than the measurements and would hand each strategy a differently shuffled table, so the numbers would carry the seed's noise rather than the strategy's effect. The seed shuffles on the way in — an ordered insert leaves a table whose physical order matches `created_at`, which makes every index scan read almost sequentially and flatters all four strategies equally. pgbench is the consumer: it ships with Postgres, it reports latency rather than an average alone, and using the standard tool keeps the argument about the index instead of the harness. 8 clients, 30 seconds, three repeats, median. The claimed row returns to `pending` with a fresh `created_at` instead of going to `done`: a consumer that drained its own queue would spend the back half of each run measuring an empty table. Every run also records the `EXPLAIN` plan, the index size, the index scans actually performed and the dead tuples left behind — throughput alone cannot tell a chosen index from an ignored one. — Confidence: High confidence — Measured on: 2026-08-22 — Database & queries - [The partial index grew three hundred and eighty times in fifteen minutes — and autovacuum never ran](https://www.muhammetsafak.com.tr/en/research/queue-table-bloat-and-autovacuum/): Under sustained churn, does a partial index stay small on a queue table, and do the default autovacuum settings keep up with it? — Kind: Measurement — Finding: With the live set holding steady at five thousand rows the partial index went from 0.1 MB to 38.2 MB — three hundred and eighty times. Its smallness comes from the live set, its bloat rate comes from throughput, and nothing connects the two. The composite index bloated less in proportion (42%) and more in absolute terms (+126 MB), and while bloating it stopped fitting in memory: its latency went from 0.52 ms to 61 seconds and its backlog climbed to 126,000. Fifteen minutes produced 1.75 million dead rows and autovacuum **did not run once** — the default threshold scales with the whole table (50 + 0.2 × 10 million ≈ 2 million) while the churn happens in a tiny subset. — Metrics: Partial index over fifteen minutes: 0.1 → 38.2 MB (380×) · Composite index, same window: 301 → 427 MB (+42%) · Autovacuum runs: 0 · Composite latency at 900 s: 61,533 ms — Method: The same harness, Postgres settings and 10-million-dead-plus-5,000-live table as the partial index measurement. Three differences, all required to ask this question. The consumer marks rows `done` rather than returning them to `pending` — the claim under test is about rows LEAVING the index, and it cannot be measured on rows that never leave. A producer runs alongside at a fixed arrival rate of 2,000/s, so the table also gets the insert traffic the previous record had to declare as missing. And the claim uses a sub-select `UPDATE` rather than `\gset`: an unthrottled consumer empties the queue in under a second and `\gset` kills the client on the empty result. The consumer is throttled to the arrival rate as well, so the queue depth holds steady — and it is sampled rather than assumed. Table size, index size, queue depth, dead tuples and the autovacuum counters were recorded every fifteen seconds; 60 samples per strategy. — Confidence: High confidence — Measured on: 2026-08-22 — Database & queries - [Postgres never turned the partial index into a generic plan: forty executions, forty custom plans](https://www.muhammetsafak.com.tr/en/research/when-does-the-planner-go-generic/): Does Postgres switch a partial-index query to a generic plan on its own inside a prepared statement — or is the 1,673-fold cliff something you have to opt into? — Kind: Measurement — Finding: Postgres declines. On the partial index all forty executions used a custom plan — the counter reads 40/0. The reason it declines is the disaster itself: a generic plan cannot use the partial index, so its estimated cost comes out high and the planner does not choose it. The composite index switches at the sixth execution exactly as documented (5/35) and loses nothing by it. So the 1,673-fold cliff is real but fenced: reaching it takes writing `plan_cache_mode = force_generic_plan`. — Metrics: Partial index, generic plans: 0 of 40 executions · Composite index, switch: execution 6 · Partial, first 5 → last 5: 0.36 → 0.20 ms · What reaching the cliff takes: force_generic_plan — Method: The same harness and the same 10-million-dead-plus-5,000-live table, across three index strategies. For each, one prepared statement was executed forty times in a single psql session and `pg_prepared_statements` was queried after every execution — the counters are session-local, which is why this measurement cannot be made from pgbench. The decision is not inferred from timings but read from the counters: `custom_plans` and `generic_plans` say directly what the planner chose on that execution. Timings arrive in pairs (the statement, then the counter query) and the parser keeps only the first. psql's aligned output pads the counter value with spaces, so output was switched to unaligned mode — the first run produced an empty series because of exactly that. — Confidence: High confidence — Measured on: 2026-08-22 — Database & queries - [How you import Chart.js decides how many kilobytes the visitor downloads](https://www.muhammetsafak.com.tr/en/research/chartjs-import-strategy/): In a real production build, what is the difference between `chart.js/auto` and a selective `Chart.register()` — in kilobytes? — Kind: Measurement — Finding: Selective registration saves 9.7 kB gzip over `chart.js/auto` (67.8 → 58.1 kB, 14.3%). The larger drop is not in the library core but in leaving unused controllers out: a page that registers only the bar chart falls to 46.0 kB — two thirds of auto. — Metrics: Selective register: 58.1 kB (-14.3%) · chart.js/auto: 67.8 kB · Bar only: 46.0 kB (-33.9%) · Island cost of the page: 65.3 kB — Method: Four separate `npx astro build` runs against the same repository, the same chart component and the same content file; only the import/register lines of `chart-render.ts` changed between runs. What is measured is the `gzip -9` size of the `dist/_astro/chart-render.*.js` chunk Rolldown emits. The build is deterministic, so one run suffices: identical input produced identical bytes, and each of the four strategies was run twice to confirm. — Confidence: High confidence — Measured on: 2026-08-19 — Frontend performance - [opcache preload cuts the deploy bill by up to fourteen times — but five of seven frameworks do not hand it to you](https://www.muhammetsafak.com.tr/en/research/opcache-preload-deploy-bill/): With `opcache.preload` on, how long is the first request seven PHP frameworks serve after a deploy, what does the gain cost, and who can actually have it? — Kind: Measurement — Finding: Preload shortens the cold first request by between 3.5× and 14.2×: Symfony drops from 35.58 ms to 2.50 ms, down to Phalcon's bare figure. But only two of the seven candidates — Symfony and CodeIgniter — publish a preload file of their own; for the other five the gain sits on the table waiting for the user to write one. Writing one is not as easy as it looks: a preload generated blindly from the classmap never brings Symfony up at all, and on CodeIgniter it does worse (5.29 ms) than the hand-picked official file (3.13 ms). And the cost does not vanish: Laravel's classmap preload takes the 62 ms it saves each visitor and writes it back as 2,340 ms of php-fpm start-up. — Metrics: Symfony, cold first request: 2.50 ms (−93%) · Candidates shipping a preload file: 2 / 7 · Laravel classmap, fpm cost: +2,340 ms · Hand-picked vs compile-everything: 3.13 → 5.29 ms — Method: The same images as the footprint and load measurements, the same PHP 8.4 build, the same nginx + php-fpm stack. Nothing was rebuilt: opcache reads `conf.d` in order, so a `02-*.ini` mounted at run time overrides the `00-bench-opcache.ini` baked into the image. Three variants per candidate — no preload, the framework's own file (found by probing the container, never hard-coded), and a uniform file that compiles every class in Composer's classmap through `opcache_compile_file`. Each variant got a fresh container, and what was measured is **the first request that container ever serves**: the readiness poll is the measurement, because a separate poll spends the first request and leaves a warm one behind. Three repeats, median reported. Preload's cost is measured as the time until php-fpm answers with a 200; that window includes nginx's own start-up, but it is the same constant in all three variants. Cross-check: the `no preload` variant reproduces the cold figures of the independent run published on 20 August to within 6%. — Confidence: High confidence — Measured on: 2026-08-22 — Language & runtime - [The PHP ecosystem does not wait for a new release — but it does not declare support either](https://www.muhammetsafak.com.tr/en/research/php-version-support-declarations/): After a PHP release ships, when do the 500 most-installed Composer packages declare that they support it, and how much does that declaration actually say? — Kind: Survey — Finding: 43.5% of installs arrive on a constraint with no upper bound at all — `symfony/console` says `>=8.4.1` today, which claims support for PHP 12 as well. Of the 280 packages that do close the top, 247 made the commitment before the version existed: `guzzlehttp/guzzle` covered 8.4 in October 2020, four years early. That leaves 33 packages that genuinely waited, at a median of 325 days. The raw medians fall version over version and read as an ecosystem speeding up; restricted to an equal observation window the trend reverses (238 → 215 → 325 days). — Metrics: Installs on an unbounded constraint: 43.5% · Committed in advance: 247 / 280 packages · Median for those who waited: 325 days · Equal window, 8.2 → 8.4: 238 → 325 days (+37%) — Method: The 500 most-installed packages were taken from Packagist's popularity endpoint, every stable release of each was pulled from the `repo.packagist.org/p2` metadata endpoint, and the `require.php` constraint each release shipped with was read. Constraints are resolved by a hand-written reader: npm's `semver` reads the same syntax differently from Composer (`~8.1` is `>=8.1 <9.0` in Composer, `>=8.1.0 <8.2.0` in semver), so it was not borrowed; the reader throws on anything it cannot parse rather than swallowing it, and the run counts those (zero this time). Which bucket a package lands in passes three filters: packages born after the release are excluded (they cannot have waited), releases with no constraint count as admitting every PHP (they block nothing), and lag is measured only on constraints that close at the top. Cross-version comparison is clipped to the shortest observation window (639 days). The scan is deterministic: re-running it the same day returns the same figures. — Confidence: High confidence — Checked on: 2026-08-22 — Language & runtime - [The fixed cost of installing a PHP framework: disk size tells you nothing](https://www.muhammetsafak.com.tr/en/research/php-framework-footprint/): How many megabytes on disk, how many files per request and how many milliseconds on the first request do seven PHP frameworks cost — and which of those numbers actually predicts throughput under load? — Kind: Measurement — Finding: Disk size predicts nothing: Yii2 has the largest vendor tree at 34.1 MB and loads only 62 files per request, among the fewest in the field. Files per request predicts nothing either: CodeIgniter loads 96 files and serves 6,431 req/s, Symfony loads 224 and serves 13,067. The one number that genuinely separates them is the first request served with a cold opcache: 2.2 ms for Phalcon, 72.2 ms for Laravel — thirty-three times. That is the compile bill the first visitor pays after every deploy, and it is measured in tens of milliseconds, not kilobytes. — Metrics: Cold first request, slowest: 72.2 ms · Cold first request, fastest: 2.2 ms · Largest vendor tree: 34.1 MB · Most files per request: 359 — Method: The same images, the same PHP 8.4.24 build and the same production set-up as the load measurement. For each candidate a fresh container was started and the following recorded: the package count in composer.lock, `du -sb vendor`, `find vendor -type f | wc -l`, the duration of the **first** request the fresh container serves (opcache empty — cold), the duration of the same request after a 5-second warm-up (warm), and on that request `get_included_files()` and `memory_get_peak_usage(false)`. Boot time is measured from the first line of the front controller to the point the response is produced. `composer install` time was taken as the median of three runs in a container with a pre-warmed package cache, using `--no-dev --optimize-autoloader --classmap-authoritative`, so it measures installation work rather than download speed. Every counter here is deterministic and reproduces exactly; installation time is the only noisy column. — Confidence: High confidence — Measured on: 2026-08-20 — Tooling comparison - [Seven PHP frameworks under identical load: the gap narrows as soon as the request does real work](https://www.muhammetsafak.com.tr/en/research/php-framework-load-test/): On the same hardware, the same PHP build and the same seven routes, how many requests a second do Laravel, Symfony, CodeIgniter, Yii2, Phalcon, Laminas and Slim serve, and at what latency? — Kind: Measurement — Finding: On an empty route the fastest is 4.4× the slowest (Slim 25,975, Laravel 5,966 req/s). As soon as the request does real work the gap closes: 3.7× for a single row from the database, 3.5× for twenty rows. Phalcon is third on an empty route and fifth once a query is involved — being a C extension buys nothing while the process waits on MySQL. And the expensive decision is not the framework: Laravel's own default `web` middleware group takes the same response from 5,858 to 2,176 req/s, so one default costs more than most of the distance between the frameworks. — Metrics: Empty route, fastest: 25,975 req/s · Empty route, slowest: 5,966 req/s · Gap: empty route → database: 4.4× → 3.7× · Laravel's web group: −63% — Method: All seven candidates ran on a single PHP 8.4.24 build, on byte-identical opcache/php.ini/php-fpm pool settings (pm=static, 8 workers) and one nginx server block. Each was installed from its official skeleton with its own documented production set-up (route/config/view caches, APP_ENV=prod, YII_DEBUG=false, Volt compiled ahead of time) and the same composer flags. All seven register exactly fifty routes with the parameterised one always at position 47. Only one candidate runs at a time; php-fpm sits on cores 0-3, nginx on 4-5, MySQL on 6-7 and the load generator on 8-11, disjoint. Every scenario runs for 15 seconds at 64 connections, nine repetitions, with the candidate order reshuffled each round. A fixed nginx reference that never reaches PHP is sampled before and after every block, recording the host capacity that measurement was given. The reported value is the best of the repetitions: the machine could not be quiesced, and interference can only ever subtract throughput, never push it past what the hardware allows. 546 load measurements, 150 host probes, zero non-200 responses. — Confidence: Medium confidence — Measured on: 2026-08-20 — Service & load ## Just Ask — Questions & Answers Visitors ask, the author answers one by one. Each entry is a self-contained page devoted to a single question. The whole section as plain Markdown: https://www.muhammetsafak.com.tr/en/just-ask.md - [Should I run several dependent operations with errgroup so the first error cancels the rest?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-run-several-dependent-operations-with-errgroup-so-the-first/): Move to `errgroup.WithContext` with a request-level timeout on top and thread ctx into every HTTP and DB call; an ignored ctx means no cancellation at all. - [Should I use chunkById instead of chunk when the same job also updates the rows it iterates?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-use-chunkbyid-instead-of-chunk-when-the-same-job/): Use `chunkById()` when there is real per-row work and never touch the cursor column; if you only update a column, switch to one set-based `UPDATE`. - [How do I cleanly implement "withX" copy methods on readonly value objects?](https://www.muhammetsafak.com.tr/en/just-ask/how-do-i-cleanly-implement-withx-copy-methods-on-readonly-value/): A readonly withX returns a new instance: `new self` with named arguments is portable, and `clone($this, [...])` fits PHP 8.5 when validation is simple. - [How does the nature of the work change on the jump from senior to staff?](https://www.muhammetsafak.com.tr/en/just-ask/how-does-the-nature-of-the-work-change-on-the-jump/): Take an ownerless org-level problem, lay the solution out in a written tech strategy, and show impact through the teams you accelerate, not your commits. - [How should I carry a correlation ID from the HTTP request all the way into queued jobs?](https://www.muhammetsafak.com.tr/en/just-ask/how-should-i-carry-a-correlation-id-from-the-http-request/): Generate the ID as a W3C `traceparent`, carry it in an SQS message attribute rather than the body, and inject it with the OTel propagator on both sides. - [My non-root container can't write to the mounted storage directory—how do I fix the permissions?](https://www.muhammetsafak.com.tr/en/just-ask/my-non-root-container-cant-write-to-the-mounted-storage-directory/): Pin the user with a build-time `ARG UID`, use `COPY --chown`, and for named volumes chown only `storage` and `bootstrap/cache` in the entrypoint. - [Should I author the OpenAPI spec first or generate it from my code?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-author-the-openapi-spec-first-or-generate-it-from/): Go contract-first with `openapi.yaml` as the single source of truth; what ends drift isn't the direction you pick but a green contract test running in CI. - [Should I use a partial index on a queue table where I only ever scan 'pending' rows?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-use-a-partial-index-on-a-queue-table-where/): Build the partial index on `WHERE status='pending'`, include the `ORDER BY` column, pair it with `FOR UPDATE SKIP LOCKED`, and pass 'pending' literally. - [How do I propagate context cancellation correctly through nested service calls?](https://www.muhammetsafak.com.tr/en/just-ask/how-do-i-propagate-context-cancellation-correctly-through-nested-service-calls/): Cancellation propagates only if you pass `r.Context()` into every downstream call, leave no `context.Background()` in the chain, and use `WithoutCancel`. - [Should I bind a Money value object to Eloquent with a custom cast or with accessors/mutators?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-bind-a-money-value-object-to-eloquent-with-a/): Integer cents in the DB, an immutable `Money` on the model: put the mapping in one `CastsAttributes` class and keep currency as a second column there. - [Should I use PHPStan generics for type-safe collections or hand-write a class per type?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-use-phpstan-generics-for-type-safe-collections-or-hand/): Default to `list` docblocks with strict PHPStan in CI; add one generic `Collection` for behavior, a concrete class only at a trust boundary. - [How do I demonstrate the broader impact expected when moving from mid-level to senior?](https://www.muhammetsafak.com.tr/en/just-ask/how-do-i-demonstrate-the-broader-impact-expected-when-moving-from/): Turn the promotion into a concrete move: pick one fuzzy problem nobody owns and carry it end to end for a quarter, from its definition to its rollout. - [How do I set a clear rule for when to log at WARN versus ERROR?](https://www.muhammetsafak.com.tr/en/just-ask/how-do-i-set-a-clear-rule-for-when-to-log/): Log at ERROR when the line would wake someone at 3am and at WARN when it would not, log a failure once at its boundary, and alert on the ERROR rate. - [Should I define the healthcheck in the Dockerfile or leave it to Kubernetes probes?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-define-the-healthcheck-in-the-dockerfile-or-leave-it/): Define readiness, liveness and startup as Kubernetes probes; keep HEALTHCHECK only if the image also runs under Compose, pointing both at one endpoint. - [How should I run the sunset process when deprecating an endpoint in my public API?](https://www.muhammetsafak.com.tr/en/just-ask/how-should-i-run-the-sunset-process-when-deprecating-an-endpoint/): Instrument usage per partner, publish a dated sunset with Sunset and Deprecation headers on every response, run brownouts, and cut when usage nears zero. - [Why does a query use an Index Scan in staging but a Seq Scan in production, and how do I diagnose it with EXPLAIN?](https://www.muhammetsafak.com.tr/en/just-ask/why-does-a-query-use-an-index-scan-in-staging-but/): Run EXPLAIN (ANALYZE, BUFFERS) in production, then ANALYZE the table and check n_dead_tup; tune autovacuum per-table for sessions and add a partial index. - [How do I detect and prevent goroutine leaks in a long-running Go service?](https://www.muhammetsafak.com.tr/en/just-ask/how-do-i-detect-and-prevent-goroutine-leaks-in-a-long/): Export NumGoroutine() as a metric, take a pprof goroutine dump at peak, make the spawn site behind the parked stacks honor ctx.Done(), then add goleak. - [Should I enable Model::preventLazyLoading only locally or in production too?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-enable-model-preventlazyloading-only-locally-or-in-production-too/): Run it fully strict and throwing in local and CI; in production keep it on but wire handleLazyLoadingViolationUsing to log without failing the request. - [What do I gain and lose by moving my status class constants to backed enums?](https://www.muhammetsafak.com.tr/en/just-ask/what-do-i-gain-and-lose-by-moving-my-status-class/): Add a backed enum on the same integer values, use tryFrom() at the boundaries, and keep the old constants as deprecated aliases while you move call sites. - [How do I design a self-healing deploy that auto-rolls back when the error rate spikes?](https://www.muhammetsafak.com.tr/en/just-ask/automated-rollback-on-error-spikes-self-healing-deploys/): Hold the new version at a canary weight and check 5xx and latency against a threshold; on breach, roll back to the last stable release and alert the team. - [Should I put my API server behind a Cloudflare Tunnel and close port 443 to the internet?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-put-my-api-behind-a-cloudflare-tunnel/): The tunnel is sound but makes Cloudflare your only way in; stay on the current Caddy setup, lock the origin to Cloudflare's IP ranges and add origin pulls. - [Canary or Blue-Green deployment for a fintech API?](https://www.muhammetsafak.com.tr/en/just-ask/canary-vs-blue-green-deployment-for-a-fintech-api/): Make Canary the default for routine releases and save Blue-Green for big cutovers needing an instant flip, since both demand expand/contract migrations. - [Why is keeping the key in .env risky when encrypting sensitive financial data — what do KMS/Vault give you?](https://www.muhammetsafak.com.tr/en/just-ask/encrypting-sensitive-financial-data-at-rest-and-key-management/): Take the key out of .env, keep it in KMS or Vault and use envelope encryption; for national IDs and card data, prefer tokenization wherever you can. - [How do I position feature flags when moving from Gitflow to Trunk-Based?](https://www.muhammetsafak.com.tr/en/just-ask/gitflow-vs-trunk-based-development-and-feature-flags/): Drop the long-lived branches, merge small changes to main continuously, keep unfinished work behind a flag that's off in prod, and delete flags once done. - [How do I isolate self-hosted CI/CD runners and build an ephemeral, clean-after-each-run environment?](https://www.muhammetsafak.com.tr/en/just-ask/isolating-and-securing-self-hosted-ci-cd-runners/): Move the runner to a register-run-once-destroy model and run jobs unprivileged; never hand over the Docker socket, and never run fork PRs on it. - [How do I distribute a Go CLI to multiple platforms with GoReleaser and Homebrew?](https://www.muhammetsafak.com.tr/en/just-ask/multi-platform-go-cli-distribution-with-goreleaser-and-homebrew/): Let one tag-triggered workflow cross-compile and publish the GitHub Release while the brews: block updates the tap formula; the tap needs its own PAT. - [How do I rewind to seconds before a disaster with WAL archiving and PITR?](https://www.muhammetsafak.com.tr/en/just-ask/point-in-time-recovery-with-wal-archiving/): Take a periodic base backup, archive WAL to S3 continuously, replay to a recovery_target_time seconds before the bad statement, and rehearse the restore. - [How do I run database migrations safely in CI/CD?](https://www.muhammetsafak.com.tr/en/just-ask/running-database-migrations-safely-in-ci-cd/): Add the column nullable, move the backfill to a separate throttled step, run migrations in their own stage, and drop the old column in a later release. - [How do I set up secretless AWS access in CI/CD with OIDC and IAM roles?](https://www.muhammetsafak.com.tr/en/just-ask/secretless-ci-cd-with-aws-iam-roles-and-oidc/): Delete the long-lived AWS keys from GitHub Secrets and assume a repo/branch-scoped IAM role over OIDC; pull non-cloud secrets from a manager at runtime. - [How do I shrink Docker images with multi-stage builds and distroless?](https://www.muhammetsafak.com.tr/en/just-ask/shrinking-docker-images-with-multi-stage-builds-and-distroless/): Leave the build tools in the builder stage: make the final stage distroless/static or scratch for Go and fpm-alpine for PHP, and run as non-root. - [How do I safely manage Terraform state with S3 + DynamoDB locking?](https://www.muhammetsafak.com.tr/en/just-ask/terraform-remote-state-and-locking-with-s3-and-dynamodb/): Move state to a versioned, encrypted S3 backend and add a DynamoDB lock table (deprecated but working), keep state per environment, and apply only from CI. - [How do I stop OPcache from causing 500s during a zero-downtime DeployerPHP deploy?](https://www.muhammetsafak.com.tr/en/just-ask/zero-downtime-deployment-with-deployerphp-and-opcache/): After flipping the symlink, gracefully reload PHP-FPM rather than restarting it; on Octane, octane:reload is mandatory and opcache_reset is optional. - [Time-series data: TimescaleDB or InfluxDB?](https://www.muhammetsafak.com.tr/en/just-ask/time-series-data-timescaledb-vs-naive-solutions/): 100M rows a day breaks a plain table, so chunk it by time with hypertables, materialize the averages as continuous aggregates, and compress the old chunks. - [How do I coordinate a zero-loss schema migration with dual-writing on a live table?](https://www.muhammetsafak.com.tr/en/just-ask/zero-loss-schema-migration-with-dual-writing-on-a-live-table/): Instead of a blocking `ALTER TABLE` on 20M rows run expand/contract: add nullable columns, dual-write, backfill in throttled batches, then drop the old. - [Why should I use a Sorted Set for a live leaderboard in Redis?](https://www.muhammetsafak.com.tr/en/just-ask/redis-data-types-using-sorted-sets-for-a-leaderboard/): Use a Sorted Set instead of plain string keys sorted in the app, since `ZADD` updates in O(log N) and `ZREVRANGE 0 99` returns the top 100 already ordered. - [When should I apply CQRS, and how do I sync the read and write models?](https://www.muhammetsafak.com.tr/en/just-ask/when-to-apply-cqrs-and-syncing-read-and-write-models/): Move reporting to a read replica and adopt CQRS only when query shapes outgrow one schema, feeding the read model from outbox events, not dual-writes. - [Should I choose NoSQL or PostgreSQL for flexible product attributes?](https://www.muhammetsafak.com.tr/en/just-ask/nosql-vs-relational-for-flexible-product-attributes/): Keep products, prices and orders in PostgreSQL and put the variable attributes in one GIN-indexed `JSONB` column; reporting alone rules out splitting. - [Race condition on balance updates: Pessimistic Lock or Redlock?](https://www.muhammetsafak.com.tr/en/just-ask/preventing-race-conditions-on-balance-updates-pessimistic-vs-redlock/): Keep the invariant in the DB with an atomic `UPDATE ... WHERE balance >= 40` or a `SELECT ... FOR UPDATE`, and save Redlock for non-DB resources. - [How do I handle poison-pill messages and a Dead Letter Queue in the queue?](https://www.muhammetsafak.com.tr/en/just-ask/poison-pill-messages-and-dead-letter-queues-in-laravel/): Put `tries` and a `backoff` on the job so it lands in `failed_jobs` at the cap, alert from a `JobFailed` listener and replay it with `queue:retry`. - [Health check design: how do I separate Liveness and Readiness?](https://www.muhammetsafak.com.tr/en/just-ask/health-check-design-liveness-vs-readiness/): Keep liveness dependency-free and check dependencies in readiness with a cached probe, since liveness restarts the pod while readiness only sheds traffic. - [How do I migrate a table to PostgreSQL partitioning with zero downtime?](https://www.muhammetsafak.com.tr/en/just-ask/zero-downtime-migration-to-postgresql-declarative-partitioning/): Stand up monthly RANGE declarative partitioning on `created_at`, backfill history in batches while the app writes, then swap names in a single transaction. - [What rules should I follow to prevent database deadlocks?](https://www.muhammetsafak.com.tr/en/just-ask/detecting-and-preventing-database-deadlocks/): Acquire locks in one global order such as ascending PK, keep transactions short, target `FOR UPDATE` at the fewest rows, and retry the rest with backoff. - [How do I handle panics in a Go HTTP server with recovery middleware?](https://www.muhammetsafak.com.tr/en/just-ask/panic-recovery-middleware-in-go-http-servers/): Wrap requests in a `defer recover()` middleware at the outermost layer, log the stack with the request id, return a generic 500 and emit a metric. - [Disaster recovery: how do I design an active-passive scenario around RTO and RPO?](https://www.muhammetsafak.com.tr/en/just-ask/disaster-recovery-strategy-setting-rto-and-rpo/): RPO 5min buys continuous cross-region replication and PITR, RTO 30min an IaC-provisioned warm standby behind Route 53 failover, rehearsed on a game-day. - [How do I prevent log storms and disk-full outages?](https://www.muhammetsafak.com.tr/en/just-ask/preventing-log-storms-and-disk-full-outages/): Collapse repeated errors into one counted line, back off retries, cap logrotate by size and count, and give `/var/log` a volume off the root disk. - [How do I build smart rate limiting against distributed brute force and DDoS?](https://www.muhammetsafak.com.tr/en/just-ask/smart-rate-limiting-against-distributed-brute-force-and-ddos/): Per-IP limits lose to rotating proxies, so key the Redis sliding-window on account + IP + ASN, add account lockout and leave volumetric floods to the edge. - [Graceful degradation: how do I isolate non-critical services under load?](https://www.muhammetsafak.com.tr/en/just-ask/graceful-degradation-isolating-non-critical-services-under-load/): Split the critical path (browse, cart, checkout) from the nice-to-haves, put those behind feature flags with short timeouts, and rehearse the kill-switch. - [How do I design eventual consistency with the Saga Pattern in a distributed system?](https://www.muhammetsafak.com.tr/en/just-ask/orchestrated-saga-for-eventual-consistency-across-services/): Split the transaction into local steps with compensating actions, driven by one orchestrator over a queue, each idempotent and published through an outbox. - [How do I prevent PostgreSQL split-brain with quorum and consensus?](https://www.muhammetsafak.com.tr/en/just-ask/avoiding-postgresql-split-brain-with-quorum-and-consensus/): Don't hand-roll failover: put promotion behind a Patroni + etcd quorum, and let a primary cut off from the majority demote itself by fencing. - [How do I set up a Circuit Breaker for a flaky third-party API dependency?](https://www.muhammetsafak.com.tr/en/just-ask/circuit-breaker-for-flaky-third-party-apis/): A breaker alone won't hold: pull `connect_timeout` and `timeout` down to 800ms-2s, isolate the dependency behind a bulkhead, and define a cached fallback. - [How do I set up CDN asset versioning: hashing and a cache strategy on deploy?](https://www.muhammetsafak.com.tr/en/just-ask/cdn-asset-versioning-and-cache-strategy-on-deploy/): Drop query-string busting: cache content-hashed filenames as `immutable`, keep the HTML short-lived, and upload the assets before you cut over. - [How do I make search-as-you-type fast with edge n-grams in Elasticsearch?](https://www.muhammetsafak.com.tr/en/just-ask/search-as-you-type-performance-with-edge-ngram-in-elasticsearch/): Drop wildcard for autocomplete; build the prefixes at index time with edge_ngram and keep a standard search analyzer so a keystroke is a plain term lookup. - [How do I stream 2-5 GB file downloads without blowing up PHP's memory?](https://www.muhammetsafak.com.tr/en/just-ask/streaming-multi-gigabyte-file-downloads-without-exhausting-php-memory/): Serve 2-5 GB files outside PHP via a presigned URL or X-Accel-Redirect; if it must go through PHP, chunk it with readStream and turn off buffering. - [How do HTTP/2 and HTTP/3 (QUIC) improve API performance?](https://www.muhammetsafak.com.tr/en/just-ask/how-http-2-and-http-3-improve-api-performance/): Turn on HTTP/2 today, since multiplexing collapses 4-5 requests per screen onto one connection; add HTTP/3 for a mobile audience and drop domain sharding. - [Which PgBouncer pooling mode should I pick — Session, Transaction, or Statement?](https://www.muhammetsafak.com.tr/en/just-ask/pgbouncer-pooling-modes-and-prepared-statements/): Pick Transaction mode for a web fleet; the price is protocol-level prepared statements, so disable them in the app or turn on PgBouncer 1.21+ support. - [Should I start a new project with microservices?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-start-a-new-project-with-microservices/): For most greenfield products, start with a modular monolith and enforce boundaries in code, promoting a module to a service only when it must scale alone. - [How do I do graceful shutdown on SIGTERM during autoscaling scale-in?](https://www.muhammetsafak.com.tr/en/just-ask/graceful-shutdown-on-sigterm-for-autoscaled-apis/): On SIGTERM drain the load balancer first, finish in-flight work inside the server.Shutdown(ctx) deadline, then align the grace period with that drain. - [How do I choose the right composite index column order in PostgreSQL?](https://www.muhammetsafak.com.tr/en/just-ask/choosing-the-right-composite-index-order-in-postgresql/): Build one (user_id, status, created_at DESC) index with equality columns first and the sort column last, then drop the single-column indexes it now covers. - [How do I prevent a Redis cache stampede (thundering herd) — mutex lock or XFetch?](https://www.muhammetsafak.com.tr/en/just-ask/preventing-cache-stampede-with-mutex-locks-or-early-expiration/): A single-flight lock plus TTL jitter covers most cases; reach for XFetch only when recompute is truly expensive, and add stale-while-revalidate either way. - [How do I cut GC pressure in Go with sync.Pool and escape analysis under load?](https://www.muhammetsafak.com.tr/en/just-ask/go-gc-pressure-sync-pool-and-escape-analysis-under-load/): The enemy behind the pauses is allocation rate: kill the top allocator with pprof, pool the hot path with sync.Pool, and tune GOGC last, not first. - [How do I debug memory leaks under Laravel Octane (FrankenPHP)?](https://www.muhammetsafak.com.tr/en/just-ask/debugging-memory-leaks-under-laravel-octane-frankenphp/): Plot the memory_get_usage curve first, bisect service providers to narrow the culprit, then reset stateful singletons in Octane's hooks and clear statics. - [Multi-tenant SaaS database isolation: separate DB, schema, or tenant_id?](https://www.muhammetsafak.com.tr/en/just-ask/multi-tenant-saas-database-isolation-for-10k-tenants/): Database-per-tenant does not scale operationally at 10k; keep tenant_id on every table and bury isolation in Postgres Row-Level Security instead. - [The payment webhook keeps re-sending the same notification; how do I set up idempotency?](https://www.muhammetsafak.com.tr/en/just-ask/webhook-idempotency-and-hmac-for-duplicate-payment-notifications/): Verify the HMAC constant-time over the raw body, return 200 fast and enqueue the work, and let a UNIQUE constraint on event_id enforce once-only. - [How do I peel the payment module off a PHP monolith with Strangler Fig?](https://www.muhammetsafak.com.tr/en/just-ask/peeling-the-payment-module-off-a-php-monolith-with-strangler-fig/): Shift payments at the gateway by 5/20/100 and validate in shadow first; the real work is splitting the tables, behind an anti-corruption layer and outbox. - [If I build edge caching with Cloudflare Workers + KV, how do I do invalidation?](https://www.muhammetsafak.com.tr/en/just-ask/edge-caching-with-cloudflare-workers-kv-and-invalidation/): The moment a price changes, write through to KV or purge the key in the same transaction or outbox; a short TTL and versioned keys are only the safety net. - [How do I set up distributed tracing (OpenTelemetry) across microservices?](https://www.muhammetsafak.com.tr/en/just-ask/distributed-tracing-with-opentelemetry-across-laravel-and-go/): Standardize on W3C Trace Context, leave propagation to the OTel SDK, and put traceparent in the queue message header, since that is where the chain snaps. - [WireGuard collides with Docker networks — how do I stabilize routing?](https://www.muhammetsafak.com.tr/en/just-ask/wireguard-and-docker-network-ip-conflicts-and-routing/): This is an addressing-plan problem, not a routing bug: pin Docker's pool in daemon.json, cut AllowedIPs down to the DB subnet, make routes persistent. - [How should I abstract the LLM provider (Ollama → Bedrock/OpenAI)?](https://www.muhammetsafak.com.tr/en/just-ask/abstracting-the-llm-provider-from-ollama-to-bedrock-or-openai/): Build one narrow complete(prompt, opts) interface with three implementations picked by config, and treat context window, latency and cost as config. - [When moving local files to S3, is EFS a good interim step?](https://www.muhammetsafak.com.tr/en/just-ask/moving-local-files-to-s3-is-efs-a-good-interim-step/): Don't make EFS the interim step; switch to a Flysystem s3 disk, route reads and writes via Storage::disk(), and migrate with dual-read for zero downtime. - [For the message schema between Laravel and Go services, Protobuf or JSON Schema?](https://www.muhammetsafak.com.tr/en/just-ask/message-schema-between-laravel-and-go-protobuf-or-json-schema/): For heavy Laravel-Go traffic pick Protobuf plus a schema registry, keep JSON Schema for light traffic, and deserialize into a typed DTO at the boundary. - [Should I put a Kafka/Redis buffer between Fluent Bit and OpenSearch when shipping logs?](https://www.muhammetsafak.com.tr/en/just-ask/should-i-put-a-kafka-buffer-between-fluent-bit-and-opensearch/): Turn on Fluent Bit's filesystem buffer first; move to Kafka once 40k/s is permanent, and keep a Redis list only for logs you can afford to lose. ## Blog — Languages - [Packaging and Distributing a CLI Tool Written in Go](https://www.muhammetsafak.com.tr/en/blog/packaging-and-distributing-a-go-cli-tool/): Writing a Go CLI tool is only half the work; versioning it, cross-compiling it, and distributing it in a way others can install effortlessly is the other half. - [TypeScript's new compiler and why build speed matters](https://www.muhammetsafak.com.tr/en/blog/typescript-new-compiler-and-build-speed/): TypeScript's compiler ported to Go, and why a fast feedback loop is so valuable for developers. - [Is PHP Dead? The 2026 Picture, by the Numbers](https://www.muhammetsafak.com.tr/en/blog/is-php-dead-2026-the-data/): A view from 18 years of PHP development — the 2026 state of PHP through W3Techs, Stack Overflow, JetBrains, and Packagist data, including the language's often-ignored weaknesses. - [PHP Constants, Enums, and Readonly: One Decision Tree for 10 Tools](https://www.muhammetsafak.com.tr/en/blog/php-constants-enums-readonly-decision-tree/): From define to asymmetric visibility — a three-axis mental model and a concrete decision matrix for getting immutability right in modern PHP. - [Building Applications with PHP in 2026: State of the Ecosystem](https://www.muhammetsafak.com.tr/en/blog/building-applications-with-php-in-2026-state-of-the-ecosystem/): The real state of PHP in 2026: language maturity, ecosystem health, and why the 'it's dead' narrative is still wrong. - [PHP 8.5 is on the way: the maturing face of the language](https://www.muhammetsafak.com.tr/en/blog/php-85-on-the-way-the-languages-maturing-face/): PHP 8.5 isn't out yet, but reading through the proposals on the table reveals how a language evolves over more than a decade. - [How Far Can You Go with Go's Standard Library](https://www.muhammetsafak.com.tr/en/blog/how-far-can-you-go-with-gos-standard-library/): A hands-on look at just how much mileage Go's rich standard library gives you, and a principled approach to deciding when to reach for an external dependency. - [PHP 8.4 is coming: property hooks and asymmetric visibility](https://www.muhammetsafak.com.tr/en/blog/php-8-4-property-hooks-and-asymmetric-visibility/): Property hooks and asymmetric visibility in PHP 8.4, and how these additions will change the way we model classes. - [Writing Tests in Go: Table-Driven Tests](https://www.muhammetsafak.com.tr/en/blog/table-driven-tests-in-go/): A hands-on introduction to Go's standard testing package and the table-driven test pattern, embracing the language's minimal testing philosophy. - [PHP 8.3: Typed Class Constants and What's New](https://www.muhammetsafak.com.tr/en/blog/php-8-3-typed-class-constants-and-new-additions/): Typed class constants, json_validate, #[Override], and dynamic constant access in PHP 8.3 — the language's steady steps toward consistency. - [Type-level programming in TypeScript: utility types](https://www.muhammetsafak.com.tr/en/blog/type-level-programming-in-typescript-utility-types/): TypeScript's built-in utility types and type transformation mechanisms: using the type system as a first-class tool. - [Using Design Patterns in PHP Without Overdoing It](https://www.muhammetsafak.com.tr/en/blog/using-design-patterns-in-php-without-overdoing-it/): Design patterns are a tool, not a goal. When to use which pattern in PHP, and when they create unnecessary complexity. - [PHP Traits: What They Are and When to Use Them](https://www.muhammetsafak.com.tr/en/blog/php-traits-what-they-are-and-when-to-use-them/): A practical explanation of PHP traits, why they exist, and how to use them to share behavior across unrelated classes without the pitfalls of multiple inheritance. - [PHP 8.2 Is Coming: Readonly Classes and New Types](https://www.muhammetsafak.com.tr/en/blog/php-8-2-readonly-classes-and-new-types/): A look at readonly classes, DNF types, and standalone type declarations in PHP 8.2, and their impact on domain modeling. - [Naming in a Codebase: An Architectural Matter](https://www.muhammetsafak.com.tr/en/blog/naming-in-a-codebase-an-architectural-matter/): Why naming is not merely a style choice, but a design decision in its own right — patterns I have observed over the years. - [End-to-end type safety with TypeScript: from API to UI](https://www.muhammetsafak.com.tr/en/blog/end-to-end-type-safety-with-typescript-from-api-to-ui/): How to carry your type contract from the backend API to the frontend interface without breaking it — and the practical approaches to get there. - [Automating repetitive tasks with Python](https://www.muhammetsafak.com.tr/en/blog/automating-repetitive-tasks-with-python/): How to move manual workflows into reliable Python scripts: which tasks are worth scripting and how to do it right. - [Designing Value Objects in Modern PHP](https://www.muhammetsafak.com.tr/en/blog/designing-value-objects-in-modern-php/): Embedding meaning into code instead of relying on primitives: why and how to design value objects in PHP. - [Go 1.18 Generics: Toward the End of a Long Wait](https://www.muhammetsafak.com.tr/en/blog/go-1-18-generics-toward-the-end-of-a-long-wait/): Go 1.18's generic support shows how a language can be reshaped thoughtfully. First impressions and trade-offs. - [PHP 8.1 Is Coming: Safer Domain Models with Enums and Readonly Properties](https://www.muhammetsafak.com.tr/en/blog/php-8-1-safer-domain-models-with-enums-and-readonly/): PHP 8.1 isn't out yet, but I'm already exploring how the upcoming native enum support and readonly properties will reshape domain modelling. - [Type Conversion and Type Coercion in PHP](https://www.muhammetsafak.com.tr/en/blog/php-type-conversion-and-type-coercion/): A practical look at PHP type conversion and coercion: gettype, settype, var_dump, and why strict_types belongs in every file. - [Generics and type inference in TypeScript](https://www.muhammetsafak.com.tr/en/blog/generics-and-type-inference-in-typescript/): Building reusable, type-safe abstractions with generics in TypeScript and making the most of type inference. - [Error handling in Go: living with the error value](https://www.muhammetsafak.com.tr/en/blog/error-handling-in-go-living-with-the-error-value/): A practical approach to embracing error handling as a language idiom in Go, a language with no exception mechanism. - [The Need for Enums in PHP: Pre-8.1 Solutions](https://www.muhammetsafak.com.tr/en/blog/php-enum-need-pre-8-1-solutions/): How we represented fixed value sets before PHP 8.1 introduced native enums, and the trade-offs of each approach. - [Coding with PHP 8.0: Attributes and the Nullsafe Operator](https://www.muhammetsafak.com.tr/en/blog/coding-with-php-8-0-attributes-and-nullsafe-operator/): PHP 8.0 is out. I share how I've been using attributes and the nullsafe operator in real projects, and what they've actually delivered. - [Preparing for PHP 8.0: union types, match, and named arguments](https://www.muhammetsafak.com.tr/en/blog/preparing-for-php-8-union-types-match-named-arguments/): PHP 8.0 isn't out yet, but the RFCs and beta releases are already readable. Here are my notes on three key features worth understanding before release. - [Writing Data Processing Scripts with Python](https://www.muhammetsafak.com.tr/en/blog/writing-data-processing-scripts-with-python/): The practical case for offloading repetitive transformation tasks to Python, with real script examples. - [Exception and Error Handling in PHP](https://www.muhammetsafak.com.tr/en/blog/exception-and-error-handling-in-php/): A practical guide to PHP exceptions and error handling: try-catch-finally blocks, multiple catch clauses, custom exception classes, and global handlers. - [Writing HTTP services in Go: is the standard library enough?](https://www.muhammetsafak.com.tr/en/blog/writing-http-services-in-go-is-the-standard-library-enough/): I explore what you get — and what you don't — when building a small HTTP service with Go's net/http package, and where the framework threshold sits. - [Typed Properties and Arrow Functions in PHP 7.4](https://www.muhammetsafak.com.tr/en/blog/php-7-4-typed-properties-and-arrow-functions/): PHP 7.4 was released in November 2019. Typed properties and arrow functions significantly strengthen the language's type system and syntax. - [Concurrency in Go: goroutines and channels in practice](https://www.muhammetsafak.com.tr/en/blog/concurrency-in-go-goroutines-and-channels-in-practice/): A hands-on look at Go's concurrency model — goroutines and channels — and what changes when you come from PHP's process model. - [Migrating to TypeScript: Type Safety in JavaScript](https://www.muhammetsafak.com.tr/en/blog/migrating-to-typescript-type-safety-in-javascript/): My practical experience adopting TypeScript in a growing frontend codebase — what I gained, what I lost, and when it actually proved its worth. - [Writing My First CLI Tool in Go](https://www.muhammetsafak.com.tr/en/blog/writing-my-first-cli-tool-in-go/): I reinforced my newly learned Go skills by building a real CLI tool — here's what the language feels like in practice and how far the standard library can take you. - [PHP 7.3: Flexible Heredoc and List Assignments](https://www.muhammetsafak.com.tr/en/blog/php-7-3-flexible-heredoc-and-list-assignments/): A hands-on look at PHP 7.3's flexible heredoc syntax and list assignment improvements, and how they contribute to better code readability. - [Readable Asynchronous Code with async/await in JavaScript](https://www.muhammetsafak.com.tr/en/blog/readable-async-code-with-async-await-in-javascript/): How async/await syntax replaced Promise chains and made asynchronous JavaScript genuinely readable — with examples. - [PHP 7.2 and Modern PHP Habits](https://www.muhammetsafak.com.tr/en/blog/php-72-and-modern-php-habits/): What PHP 7.2 introduced and how the direction of the language has shaped my day-to-day coding habits. - [Promises and Async Flow in JavaScript](https://www.muhammetsafak.com.tr/en/blog/promises-and-async-flow-in-javascript/): What Promises are in JavaScript, how to escape callback hell, and the essential patterns for chaining then/catch and managing async flow. - [PHP Closures and Variable Capture with use](https://www.muhammetsafak.com.tr/en/blog/php-closures-and-variable-capture-with-use/): What closures (anonymous functions) are in PHP, how variable capture with the use keyword works, and practical everyday examples. - [PHP 7.1: Nullable Types and the Void Return Type](https://www.muhammetsafak.com.tr/en/blog/php-7-1-nullable-types-and-void-return-type/): PHP 7.1's nullable type declarations and void return type make function signatures more readable and precise. - [Interfaces and Dependency Injection in PHP](https://www.muhammetsafak.com.tr/en/blog/interfaces-and-dependency-injection-in-php/): How I use interface definitions and dependency injection in PHP to build loosely coupled classes, illustrated with practical examples. - [Putting SOLID into practice in PHP: the Single Responsibility Principle](https://www.muhammetsafak.com.tr/en/blog/putting-solid-into-practice-in-php-single-responsibility-principle/): How I apply SRP — the S in SOLID — to PHP classes with concrete examples, moving beyond abstract theory. - [Scalar Type Declarations and Return Types in PHP 7](https://www.muhammetsafak.com.tr/en/blog/scalar-type-declarations-and-return-types-in-php-7/): A practical look at how I use scalar type declarations and return type definitions introduced in PHP 7. - [PHP 7.0: Speed and Type Declarations in the Long-Awaited Release](https://www.muhammetsafak.com.tr/en/blog/php-7-0-the-long-awaited-release-speed-and-type-declarations/): PHP 7.0 was released this week. I share my first impressions on the performance gains, scalar type declarations, and return types. - [Getting Started with ES6: let, const, and Arrow Functions](https://www.muhammetsafak.com.tr/en/blog/getting-started-with-es6-let-const-and-arrow-functions/): An introduction to the most impactful ES6 features — let, const, arrow functions, and template literals — with practical examples. - [PHP 5.6 New Features: Variadic Functions and the ** Operator](https://www.muhammetsafak.com.tr/en/blog/php-5-6-new-features-variadic-functions-and-exponentiation-operator/): An overview of PHP 5.6's variadic argument support and the new exponentiation operator, with practical examples. - [Understanding MVC for real: stop bloating your controllers](https://www.muhammetsafak.com.tr/en/blog/understanding-mvc-stop-bloating-your-controllers/): What each layer of MVC is actually responsible for, and how to keep your controllers thin. - [Traversing Large Datasets with PHP 5.5 Generators and yield](https://www.muhammetsafak.com.tr/en/blog/traversing-large-datasets-with-php-55-generators-and-yield/): The language-level approach to building large loops without blowing up memory: PHP 5.5 generators and the yield keyword. - [Organizing Code with Namespaces in PHP](https://www.muhammetsafak.com.tr/en/blog/organizing-code-with-namespaces-in-php/): Code organization that eliminates name collisions and fits the modern library ecosystem: PHP namespace usage and the use statement. - [PSR-4 and Autoloading: Escaping the Include Chain](https://www.muhammetsafak.com.tr/en/blog/psr-4-and-autoloading-escaping-the-include-chain/): Moving away from manual class includes to standard autoloading: the difference between PSR-0 and PSR-4, and Composer integration. ## Blog — Framework & Library - [Twelve years with Laravel: growing alongside a framework](https://www.muhammetsafak.com.tr/en/blog/twelve-years-with-laravel-growing-with-a-framework/): From 2014 to 2026, twelve years with Laravel — a story of maturing with a tool, outgrowing it, and choosing it again. - [Laravel 12: As the Release Cadence Matures](https://www.muhammetsafak.com.tr/en/blog/laravel-12-release-cadence-maturing/): I evaluate the changes in Laravel 12 and how the framework's annual release tempo affects project planning. - [Laravel 11's New Slim Skeleton Structure](https://www.muhammetsafak.com.tr/en/blog/laravel-11-slim-skeleton-structure/): A look at Laravel 11's leaner skeleton, the defaults that were removed, and the concrete impact on everyday development workflows. - [Async Job Processing with Laravel Queue and Supervisor](https://www.muhammetsafak.com.tr/en/blog/async-job-processing-with-laravel-queue-and-supervisor/): How to set up asynchronous job queues in Laravel using the database driver, and keep workers running reliably in production with Supervisor. - [Laravel 10: Stricter Types and the Process Layer](https://www.muhammetsafak.com.tr/en/blog/laravel-10-stricter-types-and-the-process-layer/): Laravel 10's type discipline and the new Process facade: how the framework's maturing codebase translates into better day-to-day development. - [Laravel 9: New Release Cadence and PHP 8 Compatibility](https://www.muhammetsafak.com.tr/en/blog/laravel-9-release-cadence-and-php-8-compatibility/): How Laravel 9's annual release cadence affects project planning, and what PHP 8 compatibility means for your codebase. - [Laravel Octane: the performance that comes with a persistent process](https://www.muhammetsafak.com.tr/en/blog/laravel-octane-persistent-process-performance/): How Laravel Octane eliminates per-request bootstrap overhead — and the trade-offs that come with it. - [Slimming Laravel Controllers with Action Classes](https://www.muhammetsafak.com.tr/en/blog/slimming-laravel-controllers-with-action-classes/): How to write more testable and maintainable code by moving business logic out of controllers and into single-purpose action classes. - [From monolith to modern UI with Inertia.js](https://www.muhammetsafak.com.tr/en/blog/from-monolith-to-modern-ui-with-inertia-js/): How Inertia.js delivers a single-page-app feel without a separate API, how it integrates with Laravel, and when it's the right choice. - [Laravel 8: Model Factories and the New Directory Structure](https://www.muhammetsafak.com.tr/en/blog/laravel-8-model-factories-and-new-directory-structure/): A deep dive into Laravel 8's class-based factory system and new directory layout, focused on generating test and seed data. - [Interactive Laravel Apps Without Writing JavaScript: Livewire](https://www.muhammetsafak.com.tr/en/blog/interactive-laravel-apps-without-writing-javascript-livewire/): A practical look at Livewire's server-driven interaction model — when it's the right choice, and where its limits lie. - [Laravel 6 and What LTS Really Means: Versioning Strategy](https://www.muhammetsafak.com.tr/en/blog/laravel-6-and-what-lts-really-means-versioning-strategy/): What does the Laravel 6 LTS release actually mean? Evaluating the long-term support decision against your project's lifespan and how to approach versioning strategy. - [Using Service Providers and the Container Correctly in Laravel](https://www.muhammetsafak.com.tr/en/blog/using-service-providers-and-the-container-correctly-in-laravel/): A practical guide to truly understanding Laravel's dependency resolution mechanism: how to use service providers and the IoC container the right way. - [Thinking in Components with Laravel 5.4 and Blade](https://www.muhammetsafak.com.tr/en/blog/thinking-in-components-with-laravel-5-4-and-blade/): How the @component directive introduced in Laravel 5.4's Blade templating engine lets you split views into reusable, well-defined pieces. - [Events and Listeners in Laravel](https://www.muhammetsafak.com.tr/en/blog/events-and-listeners-in-laravel/): How I use Laravel's event system to decouple side effects from the main flow — with practical examples of what you gain. - [Laravel 5.2: Multiple Authentication Guards and Route Groups](https://www.muhammetsafak.com.tr/en/blog/laravel-5-2-multiple-auth-guards-and-route-groups/): How I manage multiple user types in a single Laravel 5.2 application using guards and route groups. - [Adding shared behavior to requests with Laravel middleware](https://www.muhammetsafak.com.tr/en/blog/adding-shared-behavior-to-requests-with-laravel-middleware/): What middleware is in Laravel, how to write it, and how to centralize cross-cutting concerns like authentication in one place. - [Eloquent Relationships: hasMany, belongsTo, and Eager Loading](https://www.muhammetsafak.com.tr/en/blog/eloquent-relationships-hasmany-belongsto-and-eager-loading/): How to define hasMany and belongsTo relationships in Laravel Eloquent, and how to solve the N+1 query problem with eager loading. - [Migrating to Laravel 5: New Directory Structure and .env](https://www.muhammetsafak.com.tr/en/blog/migrating-to-laravel-5-directory-structure-and-env/): A walkthrough of the key changes when moving from Laravel 4 to 5 — directory layout, .env configuration, and application bootstrapping. - [Simplifying Database Operations with Eloquent ORM](https://www.muhammetsafak.com.tr/en/blog/simplifying-database-operations-with-eloquent-orm/): From writing raw SQL to model-based access: a practical look at Laravel's Eloquent ORM and how it fits into day-to-day development. - [Blade Template Engine: Eliminating Repetitive HTML](https://www.muhammetsafak.com.tr/en/blog/blade-template-engine-eliminating-repetitive-html/): The practical payoff of separating the view layer from logic: using Blade layouts, sections, and partials. - [Getting Started with My First Laravel 4 Project](https://www.muhammetsafak.com.tr/en/blog/getting-started-with-my-first-laravel-4-project/): The structure that comes from moving beyond raw PHP to a framework: first impressions, installation, and the basics of Laravel 4. ## Blog — Web Development - [HTTP Basic Authentication](https://www.muhammetsafak.com.tr/en/blog/http-basic-authentication/): What is HTTP Basic Authentication, how does it work, and when should you use it? A practical breakdown of the oldest auth mechanism in the web stack. - [JWT Authentication: How It Works, When It Fits, and Common Pitfalls](https://www.muhammetsafak.com.tr/en/blog/jwt-authentication-how-it-works/): A practical look at JWT authentication — token structure, signing mechanics, and the trade-offs you need to understand before reaching for it. - [Idempotency in APIs: Safely Repeating the Same Request](https://www.muhammetsafak.com.tr/en/blog/idempotency-in-apis-safely-repeating-the-same-request/): Designing API operations that produce no side effects when repeated; idempotency keys and practical implementation at the application layer. - [Real-time features in Laravel: WebSocket and broadcasting](https://www.muhammetsafak.com.tr/en/blog/real-time-features-in-laravel-websocket-and-broadcasting/): Adding live updates with Laravel Broadcasting: event-driven publishing, Pusher integration, and listening on the client side. - [Documenting APIs with OpenAPI](https://www.muhammetsafak.com.tr/en/blog/documenting-apis-with-openapi/): Deriving documentation from code and sharing a single source of truth with clients: integrating the OpenAPI specification into your daily development workflow. - [Designing APIs the Contract-First Way](https://www.muhammetsafak.com.tr/en/blog/contract-first-api-design/): How a contract-first approach aligns expectations across teams before a single line of code is written, and what it looks like in practice. - [After REST: Trying Out GraphQL](https://www.muhammetsafak.com.tr/en/blog/trying-graphql-after-rest/): While solving a real over-fetching problem with GraphQL, I weigh where REST is still sufficient and where GraphQL actually makes sense. - [API error contract: returning meaningful errors to clients](https://www.muhammetsafak.com.tr/en/blog/api-error-contract-returning-meaningful-errors-to-clients/): How binding API error responses to a consistent contract simplifies client development and debugging. - [SPA Authentication with Laravel 7 and Sanctum](https://www.muhammetsafak.com.tr/en/blog/spa-authentication-with-laravel-7-and-sanctum/): How Laravel Sanctum solves SPA authentication, and why its cookie-based approach is cleaner than token-based alternatives. - [Standardizing API responses: a consistent contract](https://www.muhammetsafak.com.tr/en/blog/standardizing-api-responses-a-consistent-contract/): How returning the same response structure from every endpoint simplifies client code and makes errors predictable. - [API versioning strategies and trade-offs](https://www.muhammetsafak.com.tr/en/blog/api-versioning-strategies-and-tradeoffs/): How do you evolve an API without breaking existing clients? A comparison of versioning strategies with their trade-offs, drawn from real-world experience. - [Task Scheduling in Laravel](https://www.muhammetsafak.com.tr/en/blog/task-scheduling-in-laravel/): How I use Laravel's task scheduler to manage multiple scheduled jobs from a single cron entry, keeping all scheduling logic readable and version-controlled inside the codebase. - [Multilingual (i18n) Applications in Laravel](https://www.muhammetsafak.com.tr/en/blog/multilingual-i18n-in-laravel/): Practical notes on adding multi-language support to Laravel: organizing language files, separating text from code, and managing locale switching. - [Laravel Notifications: Email and SMS](https://www.muhammetsafak.com.tr/en/blog/laravel-notifications-email-and-sms/): How I use Laravel Notification classes to send the same notification logic across multiple channels — email, SMS, and more. - [Formatting API Responses with Laravel Resource Classes](https://www.muhammetsafak.com.tr/en/blog/formatting-api-responses-with-laravel-resource-classes/): How to produce clean API responses with Laravel Resource classes without leaking your database model directly to clients. - [Authorization with Laravel Gates and Policies](https://www.muhammetsafak.com.tr/en/blog/authorization-with-laravel-gates-and-policies/): How to centralize authorization logic in Laravel using Gates and Policies, keeping 'who can do what' decisions clean and testable. - [Consuming Third-Party APIs: HTTP Client with Guzzle](https://www.muhammetsafak.com.tr/en/blog/consuming-third-party-apis-http-client-with-guzzle/): Connecting to external services in PHP with the Guzzle HTTP client — covering timeouts, error handling, and building a reliable request structure. - [Sending Emails in Laravel with Mailables and Templates](https://www.muhammetsafak.com.tr/en/blog/sending-emails-in-laravel-with-mailables-and-templates/): Setting up reliable, maintainable transactional emails using Laravel's Mailable class and Blade email templates. - [Pagination, Filtering, and Sorting in REST APIs](https://www.muhammetsafak.com.tr/en/blog/pagination-filtering-and-sorting-in-rest-apis/): How I design pagination, filtering, and sorting parameters in an API to present growing datasets to clients in a manageable way. - [File upload and image processing with Laravel](https://www.muhammetsafak.com.tr/en/blog/file-upload-and-image-processing-with-laravel/): A walkthrough of the end-to-end flow for file uploading, validation, and image resizing in Laravel. - [Writing JSON API Endpoints with Laravel](https://www.muhammetsafak.com.tr/en/blog/writing-json-api-endpoints-with-laravel/): A practical walkthrough of building interface-agnostic JSON API endpoints in Laravel. - [Fundamentals of RESTful API Design](https://www.muhammetsafak.com.tr/en/blog/fundamentals-of-restful-api-design/): Practical rules for making an API predictable through the triangle of resources, HTTP methods, and status codes. - [Laravel Form Validation in Practice](https://www.muhammetsafak.com.tr/en/blog/laravel-form-validation-in-practice/): A repeatable pattern for safely handling user input: Laravel validation rules and error messages. ## Blog — Interface - [Rediscovering Modern CSS](https://www.muhammetsafak.com.tr/en/blog/rediscovering-modern-css/): The problems we used to solve with JavaScript and preprocessors now have native CSS answers: container queries, :has(), and native nesting. - [React 19 and the New Face of Forms: Actions](https://www.muhammetsafak.com.tr/en/blog/react-19-forms-and-actions/): I evaluate React 19's stable-release form actions model by comparing it with previous approaches. - [Tailwind CSS 4: new engine and configuration](https://www.muhammetsafak.com.tr/en/blog/tailwind-css-4-new-engine-and-configuration/): A calm assessment of the Oxide engine and CSS-first configuration approach that Tailwind CSS 4 brings — with the composure a major version bump deserves. - [Frontend state management: Pinia in the post-Vuex era](https://www.muhammetsafak.com.tr/en/blog/frontend-state-management-pinia-after-vuex/): How Pinia replaced Vuex in the Vue ecosystem: less boilerplate, better TypeScript support, and a more mature approach to state management. - [React 18 and Concurrent Rendering](https://www.muhammetsafak.com.tr/en/blog/react-18-concurrent-rendering/): How React 18's concurrent render model changes application behavior, and what that means in practice. - [SEO Problems in Single-Page Applications and SSR Options](https://www.muhammetsafak.com.tr/en/blog/seo-problems-in-spas-and-ssr-options/): I compare the visibility problem that client-side rendering creates for search engines and evaluate server-side rendering alternatives. - [Vue 3 Composition API: Why and When](https://www.muhammetsafak.com.tr/en/blog/vue-3-composition-api-why-and-when/): I discuss what the Composition API brings over Options API in Vue 3, and when you should prefer it, with concrete examples. - [Alpine.js: A Lightweight Choice for Small Interactions](https://www.muhammetsafak.com.tr/en/blog/alpine-js-a-lightweight-choice-for-small-interactions/): When should you reach for Alpine.js, and when should you not? I discuss the right scale for UI needs that don't require a full framework. - [Tailwind CSS: Why I Switched to the Utility-First Approach](https://www.muhammetsafak.com.tr/en/blog/why-i-switched-to-tailwind-css-utility-first/): Why I adopted the utility-first CSS paradigm with Tailwind CSS v1.0, the trade-offs I encountered, and when it actually makes sense. - [How React Hooks Changed the Way We Write Components](https://www.muhammetsafak.com.tr/en/blog/how-react-hooks-changed-the-way-we-write-components/): React 16.8 introduced the Hooks API — here's how it shifted component authoring from class-based to functional, what the advantages are, and what to watch out for. - [Consuming APIs with Axios in the Frontend](https://www.muhammetsafak.com.tr/en/blog/consuming-apis-with-axios-in-the-frontend/): Practical notes on keeping the request/response layer clean in the UI using Axios interceptors, error handling, and shared configuration. - [Transitioning to Component-Based UI Architecture with Vue](https://www.muhammetsafak.com.tr/en/blog/transitioning-to-component-based-ui-architecture-with-vue/): How I shifted from page-centric thinking to component-centric thinking, and how Vue.js makes that shift practical. - [Responsive design: mobile-first CSS](https://www.muhammetsafak.com.tr/en/blog/responsive-design-mobile-first-css/): What the mobile-first CSS approach is and how to use media queries to keep a single interface looking right across different screen sizes. - [State Management in Vue with Vuex](https://www.muhammetsafak.com.tr/en/blog/state-management-in-vue-with-vuex/): Centralizing shared state across components using Vuex: state, mutations, actions, and getters explained. - [Writing Maintainable CSS with Sass](https://www.muhammetsafak.com.tr/en/blog/writing-maintainable-css-with-sass/): How I bring structure to growing stylesheets using Sass variables, nested rules, and file partials. - [Single-page application routing with Vue Router](https://www.muhammetsafak.com.tr/en/blog/single-page-application-routing-with-vue-router/): A walkthrough of the core concepts and practical setup I encountered while moving page transitions to the client side with Vue Router. - [My first reactive component with Vue.js](https://www.muhammetsafak.com.tr/en/blog/first-reactive-component-with-vue-js/): My experience moving from jQuery DOM manipulation to Vue.js's data-driven approach, and how I wrote my first reactive component. - [Building Fast, Consistent UIs with Bootstrap 3](https://www.muhammetsafak.com.tr/en/blog/building-fast-consistent-uis-with-bootstrap-3/): How to produce decent-looking interfaces without a designer: Bootstrap 3's grid system and ready-made components. - [Sending Data Without a Page Reload: jQuery and AJAX](https://www.muhammetsafak.com.tr/en/blog/sending-data-without-page-reload-jquery-ajax/): The 2014 standard for decoupling form submissions from full page loads: practical usage of jQuery's $.ajax method. ## Blog — Tools & Technologies - [Don't pick a partial index for speed](https://dev.to/muhammetsafak/dont-pick-a-partial-index-for-speed-what-i-measured-on-a-10m-row-postgres-queue-table-1mb9): Four index strategies on a 10M-row Postgres queue table: the winner did not win for the reason I gave when I recommended it, and one setting turns the win into a 1,673x loss. - [Git in Production: A Senior Engineer's Practical Guide](https://www.muhammetsafak.com.tr/en/blog/git-in-production-a-senior-engineers-practical-guide/): From workflow selection to bug hunting with bisect, rebase discipline, worktrees, and signed commits — things I noticed after years of using Git. - [Did Someone Say GitHub Actions?](https://www.muhammetsafak.com.tr/en/blog/did-someone-say-github-actions/): An introduction to CI/CD with GitHub Actions: how to set up workflows and automate your deployment process. - [Getting Started with Big Data Using Elasticsearch and Kibana](https://www.muhammetsafak.com.tr/en/blog/getting-started-with-big-data-using-elasticsearch-and-kibana/): An introduction to Elasticsearch and Kibana: the fundamentals of full-text search, data analysis, and visualization at scale. - [RabbitMQ with PHP](https://www.muhammetsafak.com.tr/en/blog/rabbitmq-with-php/): Using RabbitMQ with PHP: creating a message queue, publishing messages, and consuming them. - [Docker containerization: installation and basic usage](https://www.muhammetsafak.com.tr/en/blog/docker-containerization-installation-and-basic-usage/): A hands-on beginner's guide to Docker's container architecture, core commands, and the concepts of volumes and networking. - [Building a Testing Habit in Laravel: Switching to Pest](https://www.muhammetsafak.com.tr/en/blog/building-a-testing-habit-in-laravel-switching-to-pest/): I explain the syntax and structural differences that turned test writing from a chore into a habit when moving from PHPUnit to Pest. - [MySQL Storage Engines: InnoDB vs MyISAM](https://www.muhammetsafak.com.tr/en/blog/mysql-storage-engines-innodb-vs-myisam/): A practical comparison of MySQL storage engines: the differences between InnoDB and MyISAM, their trade-offs, and which one to choose. - [Cutting dev server startup to seconds with Vite](https://www.muhammetsafak.com.tr/en/blog/cutting-dev-server-startup-to-seconds-with-vite/): Why switching from a Webpack-based dev environment to Vite makes build times dramatically shorter. - [Testing Vue Components](https://www.muhammetsafak.com.tr/en/blog/testing-vue-components/): A practical approach to automatically verifying Vue component UI behavior: writing real-world tests with Vue Test Utils. - [npm and the Modern JavaScript Package Ecosystem](https://www.muhammetsafak.com.tr/en/blog/npm-and-the-modern-javascript-package-ecosystem/): Managing JavaScript dependencies with npm, configuring package.json correctly, and handling the practical challenges you run into in the package ecosystem. - [Writing My First Tests with PHPUnit](https://www.muhammetsafak.com.tr/en/blog/writing-my-first-tests-with-phpunit/): From installing PHPUnit to writing my first unit tests — what worked, what tripped me up, and the lessons learned along the way. - [Git workflow: branching, merging, and pull request discipline](https://www.muhammetsafak.com.tr/en/blog/git-workflow-branching-merging-and-pull-request-discipline/): Branching habits, merge strategies, and how to build a traceable change history with Git and pull requests. - [Simplifying Asset Compilation with Laravel Mix](https://www.muhammetsafak.com.tr/en/blog/simplifying-asset-compilation-with-laravel-mix/): Laravel Mix provides a fluent API that lets you compile JavaScript and CSS assets without writing Webpack configuration from scratch. - [Speeding Up API Development with Postman](https://www.muhammetsafak.com.tr/en/blog/speeding-up-api-development-with-postman/): Sharing what I learned about testing API endpoints without a browser, building collections, and integrating Postman into my development workflow. - [Migrating to Webpack: From Gulp to module bundling](https://www.muhammetsafak.com.tr/en/blog/migrating-to-webpack-from-gulp-to-module-bundling/): Why I abandoned the build pipeline I built with Gulp, and what I gained — and struggled with — when switching to Webpack. - [Publishing Your Own PHP Package on Packagist with Composer](https://www.muhammetsafak.com.tr/en/blog/publishing-your-own-php-package-on-packagist-with-composer/): I configured a PHP package from scratch and published it on Packagist so others could use it — here's how I did it. - [Building a Front-End Build Pipeline with Gulp](https://www.muhammetsafak.com.tr/en/blog/building-a-front-end-build-pipeline-with-gulp/): How I set up a front-end workflow that automates Sass compilation, JavaScript bundling, and browser reloading with Gulp. - [Consistent Development Environments for Everyone with Laravel Homestead](https://www.muhammetsafak.com.tr/en/blog/consistent-dev-environment-with-laravel-homestead/): A step-by-step walkthrough of setting up Laravel Homestead to eliminate the classic 'it works on my machine' problem across teams. - [Switching to Git: Leaving FTP File Uploads Behind](https://www.muhammetsafak.com.tr/en/blog/switching-to-git-leaving-ftp-behind/): The confidence that comes with version control: how switching from FTP to Git changed my development habits, and the basics of commits and branches. - [Switching to Composer: Stop Managing PHP Dependencies by Hand](https://www.muhammetsafak.com.tr/en/blog/switching-to-composer-stop-managing-php-dependencies-by-hand/): The practical side of moving from a pile of manual requires to modern dependency management: composer.json, autoloading, and installing packages. ## Blog — Journal - [Taking Over an Unfamiliar Codebase](https://www.muhammetsafak.com.tr/en/blog/taking-over-an-unfamiliar-codebase/): How to get a solid grasp of a codebase you've never seen before: understand first, refactor later. - [What Breaks as a Company Grows: From Owner-Run to Corporate](https://www.muhammetsafak.com.tr/en/blog/what-breaks-as-a-company-grows-from-owner-run-to-corporate/): Growth is a staircase, and the same thing breaks on every step: the capacity of informal coordination. Reading the transition from three desks at once. - [A Crisis Is Where a Company's Character Shows](https://www.muhammetsafak.com.tr/en/blog/crisis-is-where-a-companys-character-shows/): The first question asked when production goes down sets a company's culture for years. The human side of a crisis: fear, silence, and what actually changes six weeks later. - [Meetings, Reporting and Visibility Theater](https://www.muhammetsafak.com.tr/en/blog/meetings-reporting-and-visibility-theater/): The status meeting isn't an information tool — it's an insurance policy. A critique that takes meetings seriously before it takes them apart, seen from three desks. - [Performance, Promotion and Pay: There's Always a Negotiation](https://www.muhammetsafak.com.tr/en/blog/performance-promotion-and-pay-theres-always-a-negotiation/): In a corporate a raise hangs on a spreadsheet; in an owner-run company it hangs on a memory. Having a system doesn't change the outcome — only the language of the negotiation. - [Fast from scratch, slow in a live system: the real cost of brownfield in the age of agents](https://www.muhammetsafak.com.tr/en/blog/fast-from-scratch-slow-in-a-live-system/): Work an agent finishes in days takes a week inside a system that has been running for years — because there the cost isn't producing code, it's finding the rules and proving them. - [How Knowledge Flows: Hallway or Document?](https://www.muhammetsafak.com.tr/en/blog/how-knowledge-flows-hallway-or-document/): Knowledge stuck in one person's head and knowledge buried in a wiki nobody reads end up in the same place: the reasoning behind the decision is unreachable. - [Same message, different outcome: determinism in event-driven architecture](https://www.muhammetsafak.com.tr/en/blog/same-message-different-outcome-determinism-in-event-driven-architecture/): Why does the same message produce different outcomes in an event-driven system? The hidden inputs that break determinism — and four moves to win it back. - [Role Boundaries: Where There's No Job Description, Everyone Does Everything](https://www.muhammetsafak.com.tr/en/blog/role-boundaries-where-there-is-no-job-description-everyone-does-everything/): The moment a role gap gets closed by individual sacrifice it becomes invisible — and an invisible fault never gets fixed. How to draw a boundary, seen from three desks. - [When Is Process Armor, and When Is It a Shackle?](https://www.muhammetsafak.com.tr/en/blog/when-is-process-armor-and-when-is-it-a-shackle/): Process isn't a virtue — it's a coordination tax you pay. When it should be added, why it never gets removed, and how it looks from three different desks. - [How Decisions Get Made: Approval Chain or Single Signature?](https://www.muhammetsafak.com.tr/en/blog/how-decisions-get-made-approval-chain-or-single-signature/): Companies don't fail at going fast or going slow — they fail at matching the speed to the decision. A reversibility frame, and three desks to view it from. - [Corporate or Owner-Run? Size Isn't What Separates Them](https://www.muhammetsafak.com.tr/en/blog/corporate-or-owner-run-size-isnt-what-separates-them/): What separates company types isn't headcount — it's where decisions are made and how much of the reasoning gets written down. Four axes, and three desks to view them from. - [From Dual-Write to Outbox: A Log of Idempotent Consumption and Field-Level Encryption](https://www.muhammetsafak.com.tr/en/blog/from-dual-write-to-outbox-idempotent-consumption-and-field-encryption/): Lost events from dual-write pushed me to a transactional outbox, at-least-once delivery to idempotent consumption. Then I encrypted the GDPR fields at the row level with x-gdpr-sensitive. Notes from a real project. - [archlint: Enforcing Architecture Boundaries in CI, Deterministically](https://www.muhammetsafak.com.tr/en/blog/archlint-enforcing-architecture-boundaries-in-ci/): Architecture decisions stay true on the wiki and rot in the code. I built archlint: a standalone Go CLI that enforces the layer boundaries in architecture.json on every commit — with go/parser, no model, in CI. Here's why I built it this way. - [One architecture rule, three languages: archlint now does Go + TypeScript + Python](https://www.muhammetsafak.com.tr/en/blog/archlint-one-rule-three-languages/): In a polyglot repo, 'domain must not import infrastructure' is the same rule in every language — only how the import resolves differs. I added TypeScript and Python to archlint: one architecture.json enforces all three in CI. - [A Flaky-Test Detector for CommitBrief: Catching AI-Written Flaky Tests at Commit Time](https://www.muhammetsafak.com.tr/en/blog/commitbrief-flaky-test-detector/): I added a deterministic flaky-test filter to CommitBrief. Instead of asking the LLM, it catches hard-coded sleeps and unseeded randomness in changed test files at commit time — no model. Here's why I chose static analysis over an LLM prompt. - [CommitBrief Gains summary and remote: Brief a Change, Review a PR from the Terminal](https://www.muhammetsafak.com.tr/en/blog/commitbrief-summary-and-remote/): Two new commands landed in CommitBrief: summary briefs a change and its history, and remote pr reviews a PR from the terminal, leaving its comments before the human does. To clear the way for the human reviewer, not replace them. - [Vibe Coding vs AI-Assisted Development — and Why You Still Need a Senior](https://www.muhammetsafak.com.tr/en/blog/vibe-coding-vs-ai-assisted-development/): Vibe coding genuinely made shipping a product easier. But what someone without software and systems knowledge ships to production isn't the same as what a senior steering the AI ships. Three levels, three different qualities. - [Resolving an Invoice Number Collision in an E-Invoice Integration](https://www.muhammetsafak.com.tr/en/blog/resolving-invoice-number-collision-in-e-invoice-integration/): Two workers produced the same invoice number in production. A log of how I resolved the race condition vs. legal gap dilemma in a real project. - [AI-assisted self-review — what it speeds up, where it falls short](https://www.muhammetsafak.com.tr/en/blog/ai-self-review-what-it-speeds-up-where-it-falls-short/): Three months ago I built a tool to audit my own diffs. This post is not about the 'why' but the 'how much': which workflow layers it plugs into, the numbers behind the speedup, the bug patterns it keeps catching — and where it hits its limits. - [Asking a Tool to Review My Own Diff — Why I Built CommitBrief](https://www.muhammetsafak.com.tr/en/blog/asking-a-tool-to-review-my-own-diff-commitbrief/): One afternoon I ran headfirst into the limits of self-review, so I wrote a tool that audits my own diff right from the terminal: CommitBrief. A note on why I built it, how it works, and what problem it actually solves. - [Which Methodology for Which Project? — Notes from an 18-Year Developer](https://www.muhammetsafak.com.tr/en/blog/which-methodology-for-which-project-decision-matrix/): Waterfall, Agile, or Hybrid? That's the wrong question. A decision matrix from 18 years of production experience, three real case studies, and a way out of methodology religion. - [Twelve Years of This Journal: Looking Back](https://www.muhammetsafak.com.tr/en/blog/twelve-years-of-this-journal-looking-back/): Everything written in this journal from 2014 to 2026, and the story of growth it tells — and a closing. - [Visibility: why writing is a career investment](https://www.muhammetsafak.com.tr/en/blog/visibility-writing-as-a-career-investment/): Writing sharpens your thinking and compounds over time. On the career value of being visible — not as personal branding, but as an honest record. - [Being Polyglot Is an Outcome, Not a Goal](https://www.muhammetsafak.com.tr/en/blog/being-polyglot-is-an-outcome-not-a-goal/): How becoming a multi-language developer turned into a supposed goal, why it never really was one, and how I actually got there. - [Eleven Years In: A Developer's Shifting Priorities](https://www.muhammetsafak.com.tr/en/blog/eleven-years-in-a-developers-shifting-priorities/): A reflection on how my priorities as a developer have shifted over eleven years of this journal — from speed to resilience, from code to decisions. - [The Changing Craft of Writing Code in the Age of AI](https://www.muhammetsafak.com.tr/en/blog/the-changing-craft-of-writing-code-in-the-age-of-ai/): How much of writing code have AI tools taken over, and what is left for the developer? A reflection on the shifting craft. - [Mentorship and knowledge sharing: growing by helping others grow](https://www.muhammetsafak.com.tr/en/blog/mentorship-and-knowledge-sharing-growing-by-helping-others-grow/): A career post on why mentorship is not a sacrifice but one of the most effective tools for a senior developer's own growth. - [From Idea to Three Platforms: My End-to-End Feature Delivery Flow](https://www.muhammetsafak.com.tr/en/blog/feature-from-idea-to-three-platforms-end-to-end-flow/): The mature, repeatable process I follow when shipping a feature across API, web, and mobile simultaneously. - [Specialist or Generalist: A T-Shaped Career](https://www.muhammetsafak.com.tr/en/blog/specialist-vs-generalist-t-shaped-career/): On the tension between deep specialization and broad generalism, and how the T-shaped career model resolves that equation. - [Managing Updates in Expo with OTA](https://www.muhammetsafak.com.tr/en/blog/managing-expo-ota-updates/): Practical notes on shipping quick fixes without waiting for the app store review cycle, using Expo Updates — including its real limits. - [Maintaining a polyglot codebase: the cost of context switching](https://www.muhammetsafak.com.tr/en/blog/maintaining-a-polyglot-codebase-the-cost-of-context-switching/): The hidden cognitive overhead of working in multiple languages simultaneously, and how I manage it. - [Building Your Own Product Solo: The Looplio Experience](https://www.muhammetsafak.com.tr/en/blog/building-your-own-product-solo-the-looplio-experience/): An honest journal from a developer running the API, web, and mobile single-handedly — the real trade-offs of solo product development. - [Shipping a Feature Across Three Layers: API, Web, and Mobile](https://www.muhammetsafak.com.tr/en/blog/shipping-a-feature-across-three-layers-api-web-mobile/): The end-to-end workflow for delivering a single feature simultaneously across API, web, and mobile layers — lessons from building Looplio. - [Home Cloud Server: Raspberry Pi 5 Upgrade](https://www.muhammetsafak.com.tr/en/blog/home-cloud-server-raspberry-pi5-upgrade/): Building a home cloud server with Raspberry Pi 5: CasaOS, Nextcloud, RAID storage, and Cloudflare Tunnel. - [Submitting a Mobile App to the Stores with Expo](https://www.muhammetsafak.com.tr/en/blog/submitting-a-mobile-app-to-the-stores-with-expo/): A first-hand account of the preparation steps and real experience of submitting a React Native app to the App Store and Google Play using Expo and EAS Build. - [React Native Performance: List Rendering](https://www.muhammetsafak.com.tr/en/blog/react-native-performance-list-rendering/): Practical techniques for keeping large lists smooth in React Native — real-world experience with FlatList, memo, and keyExtractor. - [Side projects and open source: what they add to your career and their real cost](https://www.muhammetsafak.com.tr/en/blog/side-projects-and-open-source-career-value-and-real-cost/): An honest assessment of how side projects and open source contribute to a career: the returns, the costs, and when archiving a project is the right call. - [Feeding mobile and web with the same calendar logic (Looplio diary)](https://www.muhammetsafak.com.tr/en/blog/feeding-mobile-and-web-with-the-same-calendar-logic-looplio-diary/): The practical decisions and lessons learned while consistently serving a single business logic to both React Native and web clients in Looplio. - [Navigation and screen architecture in React Native](https://www.muhammetsafak.com.tr/en/blog/react-native-navigation-and-screen-architecture/): Practical decisions and screen architecture approaches for setting up React Native Navigation Stack, Tab, and Drawer structures in the context of Looplio. - [The job-change decision: stay or leave](https://www.muhammetsafak.com.tr/en/blog/job-change-decision-stay-or-leave/): How to turn a leaving-or-staying decision from an emotional reaction into a measurable evaluation — and distinguish legitimate signals from temporary frustration. - [Four Languages in One Year: The Mental Flexibility That Polyglot Practice Brings](https://www.muhammetsafak.com.tr/en/blog/four-languages-in-one-year-mental-flexibility-of-polyglot-practice/): A reflection on how moving between PHP, Go, Python, and TypeScript within a single year shaped the way I think about software. - [Filtering the hype: you don't have to learn every new technology](https://www.muhammetsafak.com.tr/en/blog/filtering-the-hype-you-dont-have-to-learn-every-new-technology/): How to manage your learning budget against the constant pressure of new tools and frameworks — a practical approach to deciding what to learn and when. - [First steps into mobile development with React Native and Expo](https://www.muhammetsafak.com.tr/en/blog/first-steps-into-mobile-development-with-react-native-and-expo/): A web developer's experience crossing into mobile: what I learned while setting up Looplio with React Native and Expo, and how my expectations shifted. - [Letter to my 2014 self: advice for the early years](https://www.muhammetsafak.com.tr/en/blog/letter-to-my-2014-self-advice-for-the-early-years/): Looking back at 2014, the year this journal started — what I over-prioritized, what I neglected, and what I would do differently in those early career years. - [Taking AI's Impact on Coding Seriously for the First Time](https://www.muhammetsafak.com.tr/en/blog/taking-ais-impact-on-coding-seriously/): I've been using ChatGPT for months, but something shifted this month — a curiosity turned into a real observation that made me question how I work. - [Using ChatGPT for the First Time as a Developer](https://www.muhammetsafak.com.tr/en/blog/using-chatgpt-for-the-first-time-as-a-developer/): Honest first impressions from a developer after a few days with OpenAI's newly released ChatGPT: where it impresses, and where it falls short. - [Seniority: The Responsibility That Doesn't Come with the Title](https://www.muhammetsafak.com.tr/en/blog/seniority-the-responsibility-that-doesnt-come-with-the-title/): The title often arrives before genuine seniority does. On why seniority is not about technical knowledge, but about the capacity to make decisions under ambiguity. - [Being a polyglot developer: choosing the language for the problem](https://www.muhammetsafak.com.tr/en/blog/being-a-polyglot-developer-choosing-the-language-for-the-problem/): Personal notes on why mastering multiple programming languages is a matter of tool selection, not identity. - [Simplifying My Toolset as a Software Engineer](https://www.muhammetsafak.com.tr/en/blog/simplifying-my-toolset-as-a-software-engineer/): Reviewing my tool stack during the transition from senior to staff level, I realized fewer tools lead to clearer decisions. - [Getting Started with Python: Why Yet Another Scripting Language](https://www.muhammetsafak.com.tr/en/blog/python-introduction-why-another-scripting-language/): I explain the gap Python fills in my polyglot practice, my learning journey, and a PHP developer's perspective on Python. - [First step toward polyglot: why I started learning Go](https://www.muhammetsafak.com.tr/en/blog/first-step-toward-polyglot-why-i-started-learning-go/): After more than a decade with PHP, why did I decide to pick up a second language — and why Go? - [2018 Year in Review: Where a PHP Developer Landed](https://www.muhammetsafak.com.tr/en/blog/2018-year-in-review-where-a-php-developer-landed/): An honest look at what I learned throughout 2018, how my habits shifted, and what I want to pursue next. - [Building a Calendar Events Feature with Laravel](https://www.muhammetsafak.com.tr/en/blog/building-a-calendar-events-feature-with-laravel/): How I built a full calendar feature in Laravel from scratch, handling recurrence rules, timezones, and date range queries end to end. - [Payment Integration with Laravel (iyzico): A Real-World Experience](https://www.muhammetsafak.com.tr/en/blog/payment-integration-with-laravel-iyzico-experience/): Real problems and solutions encountered while integrating iyzico payments into a Laravel project — things not in the documentation.