omeryanbas.com

Ömer Yanbaş

General Manager, Ticofab Yazılım

Journal

Problems I ran into in production, what caused them and what fixed them. Two posts a month, in English and Turkish.

2026

  1. Making technical debt visible enough to pay

    Debt nobody can see never gets budget. Give each item a cost, an interest rate and a place on the same list as features, then pay it inside feature work.

    Practice6 min read

  2. Where your team writes down its decisions

    Decisions live in chat threads and in people's heads until they vanish. A one paragraph record next to the code keeps the reasons where the work is.

    PracticeOperations6 min read

  3. Five questions for the first meeting with a client

    Ask what success is in numbers, what must keep running, who owns the accounts, what was tried before, and who decides. Then write the answers down.

    Practice6 min read

  4. Debugging: measure first, guess later

    The order that finds bugs is reproduce, narrow, measure, then theorise. Here is how to bisect changes and inputs, and why the first theory costs the most.

    Practice6 min read

  5. Long jobs get finished in small reversible steps

    How to cut a large piece of work into steps that can each ship and each be undone, with feature flags, expand and contract migrations and a real rollback.

    Practice5 min read

  6. Lab numbers, field data and a real phone

    A synthetic audit, real user data and a phone in your hand answer three different questions. Here is when each one lies and how to measure a change.

    PerformancePractice6 min read

  7. An eleven kilobyte home page: the case for static sites

    What pre rendering buys you, what it costs, and the build pipeline, page weight budget and caching rules that keep a static site small and boring.

    PerformanceWeb6 min read

  8. The scheduled job that never runs at midnight

    A schedule written in one zone on a machine running another, plus daylight saving twice a year, makes a nightly job run late, twice or not at all.

    OperationsData6 min read

  9. Your backup is a zero byte file and nobody noticed

    Backups fail quietly: a missing tool in the container, a permission, a full disk. Check the size and the row counts, and restore on a schedule.

    OperationsData4 min read

  10. Three fields that make logs worth reading

    Most logs cannot answer the one question an incident asks. A correlation id, the subject being worked on and an outcome with a reason fix that.

    OperationsPractice6 min read

  11. What your AI feature does when the credit runs out

    A model provider can fail for billing, quota or an outage. Without a fallback ladder every user sees the same generic error. How to degrade on purpose.

    AIOperations5 min read

  12. Keeping an AI feature affordable in production

    An AI feature that works can still produce a bill nobody planned for. Where the tokens go, what to cache, what to trim and how to cap spend per user.

    AIPerformance5 min read

  13. Payment webhooks: signatures, replays and idempotency keys

    Verify the signature over the raw body, reject old timestamps, store the event id, never trust the amount. A compact handler and the checks around it.

    IntegrationsSecurity5 min read

  14. From a slow query to the right index

    Find the query, read the plan, then choose the column order. A practical route from a slow page to an index that actually gets used, and its cost.

    DataPerformance5 min read

  15. Idempotent jobs: doing the work exactly once

    Queues and webhooks deliver at least once, so every handler runs twice eventually. How to make the second run harmless with a key and a constraint.

    DataIntegrations5 min read

  16. Two accessibility mistakes almost every site makes

    Heading levels chosen to match the layout, and an aria-label that hides the visible text. Both break keyboard and voice users, and both are cheap to fix.

    WebPractice5 min read

2025

  1. Self hosted fonts, privacy law and one request less

    A hosted font stylesheet hands every visitor IP address to another company before your page renders. Self hosting removes the transfer and a round trip.

    SecurityWeb6 min read

  2. What the responsive images audit is really telling you

    The audit compares the file you sent with the pixels the device needs, which is layout width times pixel ratio. Here is how to read it and what to change.

    PerformanceWeb6 min read

  3. Invisible dot underscore files travelling from macOS to your server

    Extended attributes become AppleDouble files inside archives made on a Mac, land in your web root and get served. How to spot, stop and clean them up.

    OperationsPractice5 min read

  4. The rsync flag that breaks certificate renewal

    A mirroring deploy removes everything the build did not create, including the path a certificate authority reads. How to catch it weeks before the expiry.

    OperationsSecurity6 min read

  5. Blue green deploys: check the build exit code before you restart

    A deploy script that restarts after a failed build serves a half written directory. Exit codes, an atomic switch, a smoke test and a rollback that works.

    OperationsPractice5 min read

  6. A streamed response that never closes hangs for a hundred seconds

    Tokens arrive, the answer is complete, and the request stays open until a proxy kills it. How to close a stream and test it through the real domain.

    WebAI5 min read

  7. Proxy tunnels that die after ten idle seconds

    A tunnel that closes on idle turns one long session into thousands of reconnects. On metered bandwidth the handshake traffic quietly becomes the bill.

    IntegrationsOperations6 min read

  8. How a misconfigured root exposes your .env to the internet

    When the web root points at the project directory and the server falls back to any file that exists, your .env and .git are one plain request away.

    SecurityWeb5 min read

  9. Never write to /tmp with a generic name on a shared server

    On a shared machine a generic temp filename may already exist and belong to someone else. The write fails, the read succeeds, you ship the wrong file.

    OperationsPractice5 min read

  10. Log rotation, retention and the silent cost of a full disk

    A disk creeping towards full is a slow outage: writes get refused, builds fail, backups truncate. How to find what grew and stop it growing back.

    OperationsData6 min read

  11. A hundred thousand rows pasted into a form: move it to a queue

    A synchronous bulk import dies at the proxy timeout, leaves half written state and charges the user twice. Accept, store, return, then work in chunks.

    DataPerformance5 min read

  12. The invisible suffix that split every message in two

    Two features each appended five characters after the length check ran. Every message crossed a segment boundary and the cost doubled in silence.

    MessagingPractice6 min read

  13. Why one Turkish character can double your message cost

    Short messages use a 7 bit alphabet with 160 characters, or a 16 bit one with 70. A single accented letter switches the whole message and the bill.

    MessagingData6 min read

  14. The delivery report that arrives before the record

    An asynchronous callback can reach you before the row it refers to is committed. Keep the orphan, retry the match, and stop losing final states.

    MessagingData6 min read

  15. Treating a rate limit as a permanent failure is expensive

    A 429 or a protocol throttle means come back later. A client that files it as a permanent failure throws away paid work and hides the real capacity.

    IntegrationsMessaging5 min read

  16. From 300 to 19,000 an hour: where sending throughput actually goes

    A sender stuck at 300 messages an hour is not short of CPU or bandwidth. It is waiting for one round trip at a time, and the fix is measurable.

    PerformanceMessaging5 min read

  17. The campaign that never sent: time zones in the database

    A job scheduled for 09:00 sits in the queue with no error at all. The application wrote local time, the worker reads UTC, and the offset does the rest.

    DataOperations5 min read

  18. Mail lands in spam: the From alignment nobody checks

    SPF and DKIM can both pass while mail keeps landing in spam. The header that explains it names three domains, and DMARC only accepts one answer.

    IntegrationsMessaging5 min read

  19. A strict content security policy with an inline first paint

    Inlining critical CSS and a small script is good for first paint and illegal under a strict CSP. Hashes fix it, if you compute them at the right moment.

    SecurityWeb5 min read

  20. Your entrance animation is delaying your largest paint

    An element that starts at opacity zero is never painted, so a fade in pushes Largest Contentful Paint out by the delay plus part of the animation.

    PerformanceWeb6 min read

  21. When PNG beats AVIF: images made of hard dots

    Lossy codecs are built for photographs. On a halftone screen an indexed PNG beat AVIF at every width, and the only way to know is to measure both.

    PerformanceWeb6 min read

  22. Subset the fonts, match the fallback metrics, stop the layout shift

    A page that renders 127 characters should not download 889 glyphs. Subset at build time, metric match the fallback, and the font swap stops moving things.

    PerformanceWeb5 min read

  23. The Turkish uppercase trap: i, I and the dotted İ in code

    In Turkish, i uppercases to İ and I lowercases to ı. Case folding, CSS text-transform and database collations all get this wrong by default.

    WebPractice5 min read

2024

  1. Justified Turkish text without a hyphenation dictionary

    Chrome ships no Turkish hyphenation dictionary, so justified Turkish opens rivers of white space. Insert soft hyphens at build time instead.

    WebPractice5 min read

  2. The reboot that took the site down: process managers and boot persistence

    A process manager only brings apps back after a reboot if its service unit is enabled and the process list was saved. How to check both and prove it.

    Operations5 min read

  3. When your control panel and your nginx file disagree

    Hosting panels re-render the vhost file from their own template, so hand edits vanish at the next certificate renewal. Where to put the change instead.

    OperationsWeb6 min read

  4. The nginx rule that quietly drops your security headers

    In nginx, add_header is only inherited when the child level defines none of its own. One cache header in a location removes HSTS and nosniff from it.

    WebSecurity5 min read

  5. Why redirecting every missing page to the home page costs you in search

    A blanket redirect from missing pages to the home page creates soft 404s, wastes crawl budget and hides broken links. Serve a real 404 instead.

    SearchWeb6 min read

  6. A cached 301 can break your site after a redesign

    Browsers keep permanent redirects for good. If a new site reverses an old 301, returning visitors land in a redirect loop. Here is how to find it and fix it.

    WebSearch4 min read