<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Our takes | My Geocode blog</title>
<subtitle>Opinion on the location data business: pricing, lock-in, privacy, and what the big providers get wrong.</subtitle>
<link href="https://www.mygeocode.com/blog/category/our-takes/feed.xml" rel="self"/>
<link href="https://www.mygeocode.com/blog/category/our-takes/"/>
<id>https://www.mygeocode.com/blog/category/our-takes/</id>
<updated>2026-09-21T10:29:00+00:00</updated>
<author><name>My Geocode</name></author>
<entry><title>The trouble with API keys that never expire</title><link href="https://www.mygeocode.com/blog/the-trouble-with-api-keys-that-never-expire/"/><id>https://www.mygeocode.com/blog/the-trouble-with-api-keys-that-never-expire/</id><published>2026-09-21T10:29:00+00:00</published><updated>2026-09-21T10:29:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A key issued years ago, never rotated, and still valid today is not a convenience. It is a liability nobody has actually looked at in years.</summary><content type="html">&lt;p&gt;A key that never expires is convenient in exactly the way that makes it easy to forget it exists. It gets generated once, embedded in a configuration file or an environment variable, and then it simply keeps working, indefinitely, with nobody revisiting whether it should. Years later, the person who generated it may have left the company, the project it was created for may have been decommissioned, and the key itself may be sitting in a forgotten server, a leaked repository, or an old backup, still fully valid, because nothing about the system ever asked it to prove it was still needed.&lt;/p&gt;
&lt;p&gt;This is a real, underappreciated security problem, not a hypothetical one. Keys leak through committed configuration files, through logs that captured a request header by accident, through old backups that outlive the project they belonged to. A key that never expires means every one of those leak vectors stays dangerous indefinitely, with no natural point at which the exposure closes on its own. A key that gets rotated or reviewed periodically at least bounds how long a given leak stays exploitable, even if the leak itself was never detected.&lt;/p&gt;
&lt;p&gt;We do not think the answer is forcing expiration dates that break integrations without warning, which trades one problem for a different, equally frustrating one: a key that stops working mid-production because of a rotation policy nobody communicated clearly. The answer is visibility and control that make rotation a deliberate, informed choice rather than something that either never happens or happens as an unplanned surprise. Quota headers on every response, including a count of how many of a key&amp;#039;s IP slots are in use, give an ongoing signal about whether a key&amp;#039;s usage pattern still matches what it was originally issued for, which is exactly the kind of information that should prompt a periodic &amp;quot;does this key still need to exist&amp;quot; review.&lt;/p&gt;
&lt;p&gt;The broader industry habit of treating a key as a permanent, install-it-once credential comes from prioritizing initial integration convenience over the entire lifetime of that credential&amp;#039;s existence. It is genuinely easier, on day one, to generate a key that never needs touching again. That convenience is front loaded, and the cost, an old, unmonitored, unrotated key sitting somewhere as a permanent liability, is back loaded onto a future incident nobody is thinking about on day one.&lt;/p&gt;
&lt;p&gt;We think the healthier default is treating a key less like a fixed installation and more like a credential with an ongoing relationship to the account: visible in real time through the requests it makes, reviewable periodically, and revocable without drama when a project it belonged to has actually ended. None of that requires forcing expiration on anyone. It requires making it easy enough to see what a key is actually doing that letting an old one linger forever stops being the path of least resistance.&lt;/p&gt;</content></entry>
<entry><title>Why free support tiers should still get real answers</title><link href="https://www.mygeocode.com/blog/why-free-support-tiers-should-still-get-real-answers/"/><id>https://www.mygeocode.com/blog/why-free-support-tiers-should-still-get-real-answers/</id><published>2026-09-20T22:42:00+00:00</published><updated>2026-09-20T22:42:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A support queue that only gives thoughtful answers to paying customers is telling free users their questions are not worth solving properly.</summary><content type="html">&lt;p&gt;It is common enough to be almost unremarkable: a support system with a fast, thoughtful response path for paying customers and a slow, templated, barely-read queue for everyone else. The logic is straightforward from a resourcing perspective, paying customers generate the revenue that funds support staff, so it makes sense to prioritize their tickets. The result, though, is that a free tier user with a genuine, well-formed technical question gets a canned response, or no response at all, purely because of which pricing tier they happen to be on, regardless of how legitimate or how easy to answer the question actually was.&lt;/p&gt;
&lt;p&gt;We think this creates a bad first impression at exactly the point where a first impression matters most. A developer testing an API for the first time, on the free tier, encountering a genuine problem, and getting a dismissive or absent response is learning something real about what support looks like after they start paying, not something separate from it. Free tier support quality is not a cost center disconnected from paid customer experience. It is a preview of it, and treating it as disposable sends exactly the wrong signal to the customers a company most wants to eventually convert.&lt;/p&gt;
&lt;p&gt;This does not mean every ticket, regardless of tier, needs the same response time or the same depth of hands-on engineering attention. A large paying customer with a production incident reasonably gets faster and more direct attention than a general question from someone testing on the free allowance. The distinction we care about is between prioritization, which is a reasonable operational reality, and dismissal, which is treating a question as not worth a real answer at all because of the account it came from.&lt;/p&gt;
&lt;p&gt;Part of why this matters more for us specifically is that our free tier is meant to be a genuine evaluation path, not a token gesture: 2,500 requests a day, enough to build and test a real integration. If someone hits a real, confusing problem while doing exactly that evaluation, and the support response they get is a form letter, the free tier has failed at its actual purpose, which is to let someone find out honestly whether the product works for them. A support interaction that answers nothing is part of that evaluation too, whether or not it was meant to be.&lt;/p&gt;
&lt;p&gt;We do not think this requires unlimited support staff time devoted equally to every account regardless of scale, which would not be sustainable. It requires deciding that a real question deserves a real answer, proportionate to its complexity, regardless of which tier asked it. A templated non-answer costs almost nothing to send and communicates almost exactly the wrong thing: that the question, and the person asking it, were not worth the time.&lt;/p&gt;</content></entry>
<entry><title>What &quot;real-time&quot; location data actually requires</title><link href="https://www.mygeocode.com/blog/what-real-time-location-data-actually-requires/"/><id>https://www.mygeocode.com/blog/what-real-time-location-data-actually-requires/</id><published>2026-09-20T10:13:00+00:00</published><updated>2026-09-20T10:13:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Real time gets used as a synonym for fast. What it should mean is that the answer reflects the current state of the world, not last quarter&#039;s snapshot.</summary><content type="html">&lt;p&gt;&amp;quot;Real-time&amp;quot; gets attached to a lot of location data products as shorthand for fast response times, and speed is a real and worthwhile thing to optimize for. It is also a different claim entirely from what &amp;quot;real time&amp;quot; should actually mean for data that describes something about the current state of the world: that the answer reflects what is true right now, not a fast, low-latency lookup against a dataset that itself was compiled some time ago and has not been meaningfully updated since.&lt;/p&gt;
&lt;p&gt;This distinction matters most for IP geolocation specifically, because the mapping between IP address ranges and their physical location changes over time as address blocks get reassigned, reallocated, or repurposed by the regional internet registries that manage them. A lookup that responds in a few milliseconds against a stale mapping is fast and wrong at the same time, and speed does nothing to fix the wrongness. Genuine real time IP geolocation requires the underlying mapping itself to be kept current, with a live lookup process and a cache that gets refreshed rather than treated as a fixed, one-time snapshot.&lt;/p&gt;
&lt;p&gt;We built our IP geolocation specifically around this distinction: it runs live, with caching used to keep response times low, not as a substitute for freshness, and a background retry process that keeps working through data that needs rechecking rather than a periodic cron job standing in as the only mechanism for keeping the mapping current. The goal is that the cache makes it fast without making it stale, which is a different design goal than a cache that exists purely to avoid ever recomputing anything, current or not.&lt;/p&gt;
&lt;p&gt;The same distinction applies, in a different form, to time zone data. A fast response describing an offset that has not accounted for a recent daylight saving transition or a recent government rule change is not real time in any meaningful sense, even if it returned in ten milliseconds. Real time here means the underlying reference, the IANA time zone database in this case, is being tracked and applied as it changes, not that the response arrived quickly against a table nobody has touched recently.&lt;/p&gt;
&lt;p&gt;We think &amp;quot;real time&amp;quot; deserves to be treated as a claim about data currency first and response latency second, even though latency is the part that is easiest to measure and demonstrate. A provider can genuinely optimize response time to a fraction of a second while quietly letting the underlying data go stale for months, and from the outside, a fast wrong answer and a fast right answer look identical until something downstream depends on the difference. The harder, less visible work is keeping the data itself current. That is the part that actually earns the label, and it is also the part a customer cannot verify just by timing a request.&lt;/p&gt;</content></entry>
<entry><title>Why elevation data gets treated as an afterthought</title><link href="https://www.mygeocode.com/blog/why-elevation-data-gets-treated-as-an-afterthought/"/><id>https://www.mygeocode.com/blog/why-elevation-data-gets-treated-as-an-afterthought/</id><published>2026-09-19T21:04:00+00:00</published><updated>2026-09-19T21:04:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Elevation data rarely gets its own line on a pricing page, and that absence tells you something real about how seriously it actually gets built.</summary><content type="html">&lt;p&gt;Elevation data has an image problem in this industry more than a technical one. It gets framed as a nice-to-have, a flourish added to a map view or a flight planning tool, rather than as data that genuine, practical applications actually depend on: flood risk assessment, drainage planning, agricultural work, aviation clearance calculations, construction site evaluation. None of these are niche uses. All of them need ground elevation to be treated with the same seriousness as a coordinate or an address, not as a decorative extra bolted onto a mapping product.&lt;/p&gt;
&lt;p&gt;We built elevation as a real endpoint with its own place in the product, not as an obscure optional field buried in a geocoding response that most integrations never notice exists. It is priced the same as everything else, covered under the free daily allowance and billed at the same €0.0001 per request beyond it, or included under the same €50 Unlimited key, exactly like geocoding, IP, and time zone lookups. There is no separate, higher price attached to it that would signal it is considered a specialty feature rather than a standard one.&lt;/p&gt;
&lt;p&gt;Part of why elevation gets underrated is that it is genuinely less visible in a typical consumer-facing product than an address or a pin on a map. Nobody notices elevation data directly the way they notice a wrong address on a delivery form. That invisibility to the end user does not make the underlying data less important to the systems that depend on it. A drainage calculation that is off because the elevation figure feeding it was wrong does not announce itself the way a bad address does. It shows up later, as a real-world consequence, in a decision that assumed the ground height was correct.&lt;/p&gt;
&lt;p&gt;We treat elevation as one of the parts of our product that is fully working and safe to describe concretely, alongside IP and time zone data, specifically because we think it deserves the same confidence and the same investment as any other core endpoint, not a hedge or a footnote. It is also available as an opt-in addition layered onto a standard response for callers who want ground elevation alongside a location lookup they are already making, rather than requiring a separate specialty product or a separate contract just to access it.&lt;/p&gt;
&lt;p&gt;The broader point is that elevation is exactly the kind of data category that suffers when a product treats visibility to the end user as a proxy for actual importance. Some of the most consequential uses of location data in agriculture, engineering, and risk assessment run entirely on data the end user of the resulting product will never directly see. Building that data well, and pricing it like a standard feature rather than a specialty add-on, is a bet that the invisible parts of a system deserve the same care as the visible ones, because the decisions built on top of them are just as real.&lt;/p&gt;</content></entry>
<entry><title>The case against charging extra for basic authentication methods</title><link href="https://www.mygeocode.com/blog/the-case-against-charging-extra-for-basic-authentication-methods/"/><id>https://www.mygeocode.com/blog/the-case-against-charging-extra-for-basic-authentication-methods/</id><published>2026-09-19T10:06:00+00:00</published><updated>2026-09-19T10:06:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A header, a bearer token, and a query parameter all authenticate a request the same way. Charging more for one of them is charging for a preference, not a feature.</summary><content type="html">&lt;p&gt;Authentication is one of the more mundane parts of using an API, and it is exactly the kind of mundane detail that ends up gated behind a pricing tier more often than it should be. Some providers reserve certain authentication methods, HTTP Basic auth, or a Bearer token pattern, for higher paid tiers, while a lower tier only supports a single, specific header format. The technical cost difference between validating one authentication style and another is close to nothing. What differs is how convenient each one is for a given customer&amp;#039;s existing code, which has nothing to do with how much they should pay to use the API at all.&lt;/p&gt;
&lt;p&gt;We accept a key as an X-API-Key header, an Authorization Bearer header, HTTP Basic auth with the key as the username, or a query parameter, on every host, at no extra cost for any of them. Whichever pattern already fits your existing code, whatever library or internal convention your team already uses for other APIs, is very likely already supported without needing to restructure anything just to match a specific format we happened to prefer.&lt;/p&gt;
&lt;p&gt;The reasoning behind gating authentication methods by tier is not really about cost. It is about tier differentiation for its own sake: finding features to reserve for a higher-paying customer, even features that cost nothing extra to provide, simply because having more features locked behind a higher tier makes the higher tier look more valuable on a comparison table. Authentication methods are an easy target for this because supporting several of them is genuinely low effort for the provider and genuinely convenient for the customer, which makes gating it purely a monetization decision rather than one grounded in any real cost difference.&lt;/p&gt;
&lt;p&gt;We think this kind of gating quietly punishes developers for a decision that has nothing to do with how much value they are getting from the actual data. A team whose existing tooling defaults to Bearer tokens should not pay more than a team whose tooling defaults to a custom header, when both teams are asking the exact same lookup and getting the exact same answer back. The value of the product is the response. The authentication method is plumbing, and plumbing should not carry a price tag based on which pipe happens to fit your existing wall.&lt;/p&gt;
&lt;p&gt;There is a broader principle here that applies past authentication specifically: features that cost the provider nothing extra to offer should not become artificial tier boundaries just because they can be. A tier structure built around genuine cost differences, like request volume, is defensible. A tier structure padded out with low-cost conveniences reserved for higher payers exists mainly to make the pricing page look more differentiated than the underlying product actually is.&lt;/p&gt;</content></entry>
<entry><title>Why we would rather answer with an error than a wrong guess</title><link href="https://www.mygeocode.com/blog/why-we-would-rather-answer-with-an-error-than-a-wrong-guess/"/><id>https://www.mygeocode.com/blog/why-we-would-rather-answer-with-an-error-than-a-wrong-guess/</id><published>2026-09-18T23:52:00+00:00</published><updated>2026-09-18T23:52:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A wrong answer that looks confident is worse than an honest failure. An error tells you to check something. A confident wrong guess tells you nothing is wrong.</summary><content type="html">&lt;p&gt;An API that always returns something, even for a request it cannot answer well, looks more capable on the surface than one that sometimes returns a clear error instead. The impression is misleading. A response that guesses at an answer rather than admitting uncertainty is not more useful. It is more dangerous, specifically because it looks exactly like a confident, correct response and gives the caller no signal to check further before acting on it.&lt;/p&gt;
&lt;p&gt;We would rather return a clear error, or a response that plainly indicates a low-confidence or partial match, than silently substitute a best guess dressed up as a normal answer. This matters most for forward geocoding, reverse geocoding, and autocomplete, exactly the endpoints where a partial or ambiguous address can tempt a system into returning the closest plausible match rather than acknowledging that the input did not resolve cleanly. A closest plausible match presented as a normal result is the single most likely way for bad location data to end up embedded in a shipment, a service area check, or a customer record, because nothing about the response signals that anything was uncertain.&lt;/p&gt;
&lt;p&gt;This is also part of why we are deliberately cautious about claiming a specific, verified accuracy figure for geocoding and autocomplete rather than asserting these are fully finished, proven features. A system confident enough to publish a specific accuracy number has to be equally confident about what happens on the inputs that number does not cover, and the honest answer, for any geocoding system, includes some share of addresses that should come back as unresolved or ambiguous rather than force-fit into an answer.&lt;/p&gt;
&lt;p&gt;An error response costs something in the moment: it requires the calling application to handle a failure case instead of always getting a clean object back, and it can feel like a worse developer experience on the surface, since a guess that happens to be right looks identical to an error-free response and a guess that happens to be wrong looks identical too, until someone downstream notices. That is exactly the problem. A guess and a correct answer are indistinguishable from the outside, which is precisely why a system that cannot tell the difference internally should not paper over that gap by picking one and presenting it as certain.&lt;/p&gt;
&lt;p&gt;We think this preference, a clear failure over a confident guess, should be a baseline expectation for any data API, not just ours. A caller can build real error handling around a system that tells the truth about what it does not know. No caller can build reliable error handling around a system that always answers, because there is no way to distinguish the requests it actually got right from the ones it silently guessed at and happened to land on the wrong side of.&lt;/p&gt;</content></entry>
<entry><title>What a coupon code says about a company&#039;s pricing confidence</title><link href="https://www.mygeocode.com/blog/what-a-coupon-code-says-about-a-company-s-pricing-confidence/"/><id>https://www.mygeocode.com/blog/what-a-coupon-code-says-about-a-company-s-pricing-confidence/</id><published>2026-09-18T11:36:00+00:00</published><updated>2026-09-18T11:36:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A permanent 20 percent off coupon floating around the internet is not a discount. It is evidence that the listed price was never the real price.</summary><content type="html">&lt;p&gt;Search for almost any subscription software product and a discount code turns up somewhere: a blog post, a forum thread, an affiliate site, offering some percentage off that has apparently been valid for months or years. A coupon that never expires and is trivially easy to find is not really a coupon in the sense of a limited, genuine promotion. It is closer to a permanent second price list that exists specifically so the advertised price can stay artificially high for anyone who does not go looking for the workaround.&lt;/p&gt;
&lt;p&gt;This pattern relies on a specific kind of customer behavior: enough people will pay the full listed price without searching for a discount that the inflated number remains worth publishing, while everyone who does search finds the real price and feels like they got a deal, when in fact they just found the price that was always closer to what the product should cost. Both groups are being sold the same product. One of them is paying more, purely because they did not know to look for a code.&lt;/p&gt;
&lt;p&gt;We priced My Geocode at the number we think the product is actually worth, not a number designed to be discounted down to the real price through a code that circulates separately from the pricing page. €0.0001 per request, €50 a month for Unlimited, 2,500 free requests a day. Those are the numbers, not a starting point for negotiation through a coupon a customer has to go find somewhere else to get the price everyone else is actually paying.&lt;/p&gt;
&lt;p&gt;A permanent, widely known discount code is also a strange signal about how a company thinks about its own customers: it assumes a meaningful share of them either will not notice the gap between the listed price and the real price, or will not bother to look for the code, and prices accordingly for that group specifically. We think this is a bad way to treat customers who are simply less inclined to search for a workaround before paying for something. The price on the page should be the price, for everyone, whether or not they thought to check a coupon site first.&lt;/p&gt;
&lt;p&gt;None of this is an argument against occasional, genuine promotions with a real, limited window: a launch discount, a seasonal offer, something with an actual end date and a specific reason for existing. The difference between that and a permanently circulating code is the difference between a real event and a permanent, unofficial second price list. A pricing page confident in its own number does not need a workaround quietly available elsewhere to make that number bearable. It just needs the number to already be right.&lt;/p&gt;
&lt;p&gt;We priced My Geocode at €0.0001 per request and €50 a month for Unlimited because those are the numbers we are willing to stand behind in public, to every customer, with no separate quieter number waiting to be discovered by whoever happens to search for one.&lt;/p&gt;</content></entry>
<entry><title>Why migration should take an afternoon, not a quarter</title><link href="https://www.mygeocode.com/blog/why-migration-should-take-an-afternoon-not-a-quarter/"/><id>https://www.mygeocode.com/blog/why-migration-should-take-an-afternoon-not-a-quarter/</id><published>2026-09-18T00:44:00+00:00</published><updated>2026-09-18T00:44:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>If switching a location API takes a quarter, the previous integration was designed to make leaving expensive, whether or not that was the stated intention.</summary><content type="html">&lt;p&gt;A migration project that gets scoped as a quarter of engineering time to switch a location data provider is usually not a quarter of genuinely necessary work. It is a quarter of work created by design decisions made years earlier: a proprietary response format that has to be unwound field by field, an SDK whose method calls are scattered through a codebase in places nobody documented, error handling built around one provider&amp;#039;s specific status codes. None of that complexity is inherent to the idea of looking up an address or an IP. All of it is inherited from choices that made the original integration convenient at the cost of making a future migration expensive.&lt;/p&gt;
&lt;p&gt;We built 17 compatibility hosts specifically to make that quarter unnecessary for anyone whose existing integration already speaks one of those provider shapes. If your code calls a well-known geocoding or IP API&amp;#039;s endpoint and parses its specific response format, pointing that same code at our matching compatibility host should require changing a base URL and an API key, not rewriting the parsing logic that has been working fine for years. Authentication accepts a key as a header, a bearer token, HTTP Basic auth, or a query parameter, so whatever pattern your existing code already uses is very likely already supported.&lt;/p&gt;
&lt;p&gt;An afternoon-scale migration is not a claim we make lightly, because we know exactly how much effort it took on our side to make that true: matching another provider&amp;#039;s response shape field by field, testing it against real requests, and holding that shape stable so a customer&amp;#039;s existing code has no reason to notice a difference beyond where the request goes. That work is front loaded onto us specifically so it does not have to happen, again, downstream, in every customer&amp;#039;s codebase that wants to test whether switching is worth it.&lt;/p&gt;
&lt;p&gt;The broader point extends past our own compatibility hosts: a migration that takes a quarter is diagnostic information about the previous integration, not a natural property of switching providers in general. If leaving a provider requires a multi-month project, someone, somewhere, benefited from that friction existing, whether or not it was built deliberately to create it. A provider genuinely confident in its data, pricing, and reliability has no reason to make switching away difficult, because the entire pitch should be that a customer who tries it will not want to leave, not that leaving is too expensive to attempt.&lt;/p&gt;
&lt;p&gt;We would rather compete on whether the product is worth staying with, evaluated honestly, on the same afternoon a customer could just as easily switch away. Making that afternoon possible cost us real engineering effort. We think it is effort that should have been spent, and that any provider unwilling to spend it is quietly telling you something about how confident it actually is in what it is selling.&lt;/p&gt;</content></entry>
<entry><title>The trouble with dashboards that hide your real usage</title><link href="https://www.mygeocode.com/blog/the-trouble-with-dashboards-that-hide-your-real-usage/"/><id>https://www.mygeocode.com/blog/the-trouble-with-dashboards-that-hide-your-real-usage/</id><published>2026-09-17T11:50:00+00:00</published><updated>2026-09-17T11:50:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A usage dashboard that only updates once a day is not really a real time picture at all. It is just yesterday&#039;s number wearing today&#039;s date on it.</summary><content type="html">&lt;p&gt;A usage dashboard is supposed to answer a simple question at any moment: where do I stand right now. Plenty of dashboards answer a slightly different question instead: where did you stand as of the last time our billing system reconciled usage, which might be an hour ago, might be this morning, and during a traffic spike is exactly the gap that turns a manageable situation into a surprising overage or an unexpectedly exhausted free allowance.&lt;/p&gt;
&lt;p&gt;We think the dashboard is the wrong place to put this information as the sole source of truth, not because dashboards are bad, but because a dashboard is inherently a step removed from the request that actually matters. The response to that specific request is the one place guaranteed to reflect your exact standing at that exact moment, because it is generated at the same time the request itself is being counted. That is why every response from My Geocode carries quota headers directly: your limit, what you have used, your remaining free allowance, your network&amp;#039;s usage, remaining prepaid credit, and when the quota resets. You do not have to open a separate tab and hope it has caught up.&lt;/p&gt;
&lt;p&gt;This matters most in exactly the situations where a lagging dashboard fails hardest: a sudden spike in traffic, a batch job that consumes a large chunk of allowance quickly, or a launch day where usage looks nothing like a normal day. A dashboard on a delay will keep showing a comfortable number well past the point where the real number has become urgent. Headers on the actual response you just received cannot lag in the same way, because they are not a separate reporting system trying to catch up. They are generated as part of answering the request itself.&lt;/p&gt;
&lt;p&gt;A dashboard still has real value as a place to see trends over time, review history, or manage account details that do not change request by request. We are not arguing dashboards should not exist. We are arguing they should not be the only place, or the primary place, where a developer learns whether they are about to run out of allowance or credit. That information needs to be available at the moment it is actionable, which is the moment of the request, not sometime later when a dashboard&amp;#039;s own refresh cycle gets around to reflecting it.&lt;/p&gt;
&lt;p&gt;The deeper issue with a lagging dashboard is that it can create a false sense of security that is worse than having no visibility at all. A developer who checks a dashboard, sees a comfortable number, and proceeds with confidence has been actively misled by a tool that was supposed to prevent exactly that outcome. Real time information in the response itself avoids that trap entirely, because there is no separate system whose staleness needs to be accounted for before trusting the number.&lt;/p&gt;</content></entry>
<entry><title>Why open data beats licensed data for most use cases</title><link href="https://www.mygeocode.com/blog/why-open-data-beats-licensed-data-for-most-use-cases/"/><id>https://www.mygeocode.com/blog/why-open-data-beats-licensed-data-for-most-use-cases/</id><published>2026-09-17T00:36:00+00:00</published><updated>2026-09-17T00:36:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Licensed data comes with a contract that can change under you. Open data comes with a community that has no reason to renegotiate your access later.</summary><content type="html">&lt;p&gt;Licensed data has an obvious appeal: a single vendor controls it, curates it, and can be held contractually accountable for its quality. It also comes with a structural risk that is easy to underweight when a deal is first signed: the license is a relationship with one party, and that party can change the terms, raise the price, or restrict access in a future renewal in ways the original agreement never fully protected against. A dataset your product depends on can become more expensive, or less available, for reasons that have nothing to do with the data itself and everything to do with a negotiation you were not part of.&lt;/p&gt;
&lt;p&gt;Open, community-maintained reference data does not eliminate risk, but it changes its shape in a way we think is generally healthier for a product built on top of it. The IANA time zone database is a clear example: it is maintained openly, tracked by contributors with a direct stake in its accuracy, and available to anyone building on top of it without a licensing negotiation standing between the data and the product. Country codes under ISO 3166-1, and subdivision codes under ISO 3166-2, work the same way, as widely adopted reference standards rather than something a single company controls access to.&lt;/p&gt;
&lt;p&gt;Building on top of open reference standards where they exist, and reserving proprietary effort for the parts of the product that genuinely need it, like the matching logic and coverage work behind geocoding itself, lets us avoid the renegotiation risk that comes with sourcing something like time zone rules or country codes from a single exclusive vendor. Nobody can revoke our access to the IANA database or double its price at the next contract renewal, because there is no exclusive contract standing between it and anyone using it.&lt;/p&gt;
&lt;p&gt;This does not mean open data is automatically higher quality than licensed data, or that licensing is always the wrong choice. Some data genuinely requires the kind of sustained, funded, centralized effort that only a commercial vendor can realistically provide, and paying for that is a reasonable trade when no open equivalent exists at comparable quality. The point is narrower: where a solid, actively maintained open standard already exists, building a proprietary, licensed alternative on top of the same underlying facts mostly just recreates vendor risk that did not need to exist in the first place.&lt;/p&gt;
&lt;p&gt;We think this is a case where behind-the-scenes data sourcing decisions actually matter to a customer, even though they never see them directly. A product built on open reference data where it is available is less exposed to a single vendor&amp;#039;s future decisions, which means the product itself is less likely to change underneath a customer for reasons that have nothing to do with anything the customer did.&lt;/p&gt;</content></entry>
<entry><title>What &quot;unlimited requests&quot; should mean, precisely</title><link href="https://www.mygeocode.com/blog/what-unlimited-requests-should-mean-precisely/"/><id>https://www.mygeocode.com/blog/what-unlimited-requests-should-mean-precisely/</id><published>2026-09-16T11:09:00+00:00</published><updated>2026-09-16T11:09:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Unlimited should be a testable claim, not a mood. If a plan has a real ceiling anywhere, that number belongs on the pricing page, not the word unlimited.</summary><content type="html">&lt;p&gt;&amp;quot;Unlimited&amp;quot; is a word with a precise meaning that gets used loosely often enough that the precise meaning has started to feel almost naive to expect. It should mean exactly what it says: no ceiling on the number of requests you can send under that plan, at any rate your actual usage reaches. It should not mean a very large number that the provider has not disclosed, a rate that gets throttled once usage crosses an internal threshold, or a plan that technically has no stated limit but comes with a fair use clause that functions as an undisclosed one.&lt;/p&gt;
&lt;p&gt;Our Unlimited key, at €50 a month, means the first definition and only the first definition. There is no internal threshold above which requests start getting throttled, no fair use policy standing in for a number we would rather not publish, and no distinction between what the plan advertises and what it actually permits once you use it heavily. If we ever built in a genuine technical safeguard, the honest response would be to rename the plan and publish the real number, not keep the word and quietly attach a condition to it.&lt;/p&gt;
&lt;p&gt;We think a useful test for whether an unlimited claim is genuine is whether it is falsifiable in a specific, checkable way: can a customer send an unusually large volume of requests in a short period and see whether the plan actually holds, or does the provider have language somewhere that lets them redefine &amp;quot;unusual&amp;quot; after the fact, in a way the customer could not have predicted from the plan&amp;#039;s terms. A claim that can always be explained away after the fact is not really a claim. It is a placeholder for whatever the provider decides later.&lt;/p&gt;
&lt;p&gt;This distinction matters because unlimited plans exist specifically for customers who need to stop thinking about their request volume as a cost center to manage. That is the entire value proposition: pay a flat amount and stop counting. A plan that quietly still has a ceiling defeats that purpose in the worst possible way, because the customer who bought it specifically to stop worrying about limits is the one most likely to be surprised when a hidden one gets enforced, since they were the one relying most heavily on the word meaning what it said.&lt;/p&gt;
&lt;p&gt;We are not arguing every provider needs to offer an unlimited tier, or that a capped, clearly priced plan is worse than an unlimited one. A clearly stated cap is honest on its own terms. What is not honest is calling a capped plan unlimited because the cap is set high enough that most customers will never personally test it. The word should describe a property of the plan, tested and true at any volume, not a marketing impression that happens to hold for the median customer and quietly fails for anyone who actually needed the promise to be literal.&lt;/p&gt;</content></entry>
<entry><title>Why per-country pricing tiers are a bad idea</title><link href="https://www.mygeocode.com/blog/why-per-country-pricing-tiers-are-a-bad-idea/"/><id>https://www.mygeocode.com/blog/why-per-country-pricing-tiers-are-a-bad-idea/</id><published>2026-09-15T22:21:00+00:00</published><updated>2026-09-15T22:21:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Charging more to look up an address in one country than another treats geography itself as a pricing lever instead of plain, ordinary data to serve.</summary><content type="html">&lt;p&gt;Some location data pricing pages carry a table that charges different rates depending on which country a lookup targets: a lower rate for countries with widely available, well-established address data, and a higher rate for countries where coverage is harder to build and maintain. The logic sounds defensible on its face, harder data costs more to source, so it should cost more to query. In practice, per-country pricing turns geography into a pricing lever in a way that is difficult to justify once you look closely at who ends up paying more and why.&lt;/p&gt;
&lt;p&gt;We charge one flat rate per request regardless of which country a lookup targets. Every endpoint and every compatibility host costs the same, worldwide, whether the address, IP, or coordinate in question is in a market with abundant public geographic data or one with comparatively sparse coverage. There is no country-by-country price table to navigate before you can estimate a bill.&lt;/p&gt;
&lt;p&gt;Part of our reasoning is practical: per-country pricing adds real complexity to something that should be simple to reason about. A customer with global traffic, which describes most real applications operating online, cannot calculate an expected bill from a single rate. They have to model the country mix of their traffic and multiply each segment by a different number, turning a straightforward unit economics calculation into a small forecasting exercise that has to be redone every time the traffic mix shifts.&lt;/p&gt;
&lt;p&gt;There is a fairness dimension too, one that is easy to miss if you only think about it from the pricing table rather than from who is actually affected. Countries and regions with less established digital infrastructure or less mature open geographic data tend to be lower income markets, on average, more often than not. Charging a premium specifically for looking up locations in those markets, because the underlying data was harder to build, effectively taxes exactly the users and applications serving those regions, at the moment they are trying to reach a market that a flat global rate would treat the same as any other.&lt;/p&gt;
&lt;p&gt;We think a single global rate is the more honest reflection of how the product should be evaluated: not by how expensive a specific country was to source data for, but by what a request costs to serve across the system as a whole. Some countries genuinely require more ongoing work to keep accurate. That is a cost we absorb as part of running a worldwide service, not a cost we pass selectively onto whichever customer happens to be querying the harder market that week. A worldwide product should have a worldwide price, and geography should describe where a lookup points, not what it costs to ask.&lt;/p&gt;
&lt;p&gt;This is also simply easier to keep honest over time. A single global rate has no table to quietly revise country by country as internal costs shift. One number, applied everywhere, is a promise that is much harder to walk back selectively than a pricing grid nobody outside the company ever fully audits.&lt;/p&gt;</content></entry>
<entry><title>The case for treating postal code lookups as first class</title><link href="https://www.mygeocode.com/blog/the-case-for-treating-postal-code-lookups-as-first-class/"/><id>https://www.mygeocode.com/blog/the-case-for-treating-postal-code-lookups-as-first-class/</id><published>2026-09-15T11:02:00+00:00</published><updated>2026-09-15T11:02:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A postal code endpoint priced and documented like an afterthought will get built like one too. Treating it seriously starts with treating it equally.</summary><content type="html">&lt;p&gt;Product priorities show up in pricing structure and documentation depth long before they show up in any explicit statement about what matters most. An endpoint tucked into a lower pricing tier, or documented in three sentences next to a fully detailed page for a flagship feature, is communicating a real fact about internal priority, whether or not anyone intended to communicate it. Postal code lookups are a common victim of this pattern: technically available, rarely invested in, and treated as a minor utility relative to full geocoding.&lt;/p&gt;
&lt;p&gt;We priced postal code lookups the same as every other endpoint on purpose, specifically to avoid that quiet demotion. It is covered under the same free daily allowance, billed at the same €0.0001 per request beyond that, or included under the same €50 Unlimited key, exactly like geocoding, IP lookups, time zone, or elevation. There is no discount tier that signals postal lookups are considered less valuable, and no premium tier that signals the opposite. It sits at the same level as everything else, because we think it should.&lt;/p&gt;
&lt;p&gt;Equal pricing is a starting point, not the whole argument. The deeper reason postal code lookups deserve first class treatment is that the underlying data genuinely warrants the same seriousness as any other kind of location data. Postal systems are not a simplified version of geocoding. They are their own category of structure, varying by country in format, in the size of area a single code covers, and in how directly the code maps onto administrative boundaries. Building this correctly across multiple countries takes real, sustained attention, the same kind that a flagship geocoding feature gets by default because it is assumed to be the important one.&lt;/p&gt;
&lt;p&gt;Treating an endpoint as first class also means it gets the same documentation standard: real examples, a clear description of what data is returned and how it is structured, and honest notes about coverage limitations by country rather than a vague blanket claim. An endpoint documented thinly because it is assumed to be simple tends to stay simple in exactly the ways that matter, because nobody is looking closely enough to notice where it falls short.&lt;/p&gt;
&lt;p&gt;There is a practical payoff to this beyond fairness in how we allocate engineering attention. A lot of real applications, shipping calculators, tax jurisdiction checks, service area validation, depend more directly on a correct postal code resolution than on a full street-level geocode. Treating postal lookups as a minor feature relative to geocoding gets the actual dependency backwards for exactly the applications that need this data the most. Giving it equal pricing and equal documentation is not a symbolic gesture. It is closer to correcting a category error that the rest of the industry has mostly inherited without examining.&lt;/p&gt;</content></entry>
<entry><title>Why time zone bugs are usually a testing problem, not a data problem</title><link href="https://www.mygeocode.com/blog/why-time-zone-bugs-are-usually-a-testing-problem-not-a-data-problem/"/><id>https://www.mygeocode.com/blog/why-time-zone-bugs-are-usually-a-testing-problem-not-a-data-problem/</id><published>2026-09-14T22:40:00+00:00</published><updated>2026-09-14T22:40:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Most time zone bugs do not come from bad data. They come from code that was never tested against the one week a year when the rules actually change.</summary><content type="html">&lt;p&gt;A time zone bug almost never shows up on a normal Tuesday. It shows up during the specific week a daylight saving transition happens, or in a region whose government just changed its offset rules with little notice, or at the exact boundary between two zones where an edge case in coordinate-to-zone mapping picks the wrong side. The rest of the year, code that handles time zones badly runs without any visible problem at all, which is exactly what makes these bugs so persistent: the failure mode is rare by design, so it rarely gets caught until it actually happens in production.&lt;/p&gt;
&lt;p&gt;We think most of these bugs get blamed on the data when they are really a testing gap. The IANA time zone database, which underlies most serious time zone handling including ours, tracks these transitions and rule changes as they happen. The data being available is not the same as an application correctly exercising the code paths that only run during a transition week or only apply to the handful of regions with unusual rules. If a test suite never simulates a daylight saving boundary, or never runs a lookup against a region with a non-standard half-hour or 45-minute offset, the underlying data being correct will not save an application from a bug that only its own untested code path can prevent.&lt;/p&gt;
&lt;p&gt;This is a case where the fix is boring and specific rather than exciting: test explicitly against the calendar dates when transitions occur, not just against an arbitrary date picked because it was convenient. Test against a handful of edge case regions with unusual offsets deliberately, not only against the common, round-number time zones that most development happens to occur in. None of this requires new data. It requires deciding that the rare week is worth testing as carefully as the common one, since the rare week is exactly when the bug will surface for a real user.&lt;/p&gt;
&lt;p&gt;There is a related trap worth naming: caching a time zone offset for a location once and reusing that cached value indefinitely. An offset that was correct in July can be wrong in December once daylight saving shifts it, and a cache that does not account for that will confidently serve a stale answer without any indication that anything went wrong. This is not a data quality problem either. It is an architecture decision that assumed a fact would stay constant when the entire nature of the data is that it periodically does not.&lt;/p&gt;
&lt;p&gt;We describe our time zone endpoint as one of the parts of the product that is fully working, because the underlying reference data is actively maintained and the lookup logic is built to account for these transitions directly rather than assuming a static offset. The larger point applies beyond our own product: a time zone bug reaching a customer is rarely proof that the source data was wrong. It is much more often proof that nobody wrote a test for the one week a year, or the one region, where the rules actually change.&lt;/p&gt;</content></entry>
<entry><title>What IPv6 adoption still gets wrong across this industry</title><link href="https://www.mygeocode.com/blog/what-ipv6-adoption-still-gets-wrong-across-this-industry/"/><id>https://www.mygeocode.com/blog/what-ipv6-adoption-still-gets-wrong-across-this-industry/</id><published>2026-09-14T10:18:00+00:00</published><updated>2026-09-14T10:18:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>An IP lookup API that still treats IPv6 as a minor edge case is quietly treating a growing share of real internet traffic as an afterthought.</summary><content type="html">&lt;p&gt;IPv6 has been available for long enough that treating it as a secondary concern is no longer a reasonable engineering shortcut, yet plenty of IP-related tooling still behaves as though IPv4 is the real traffic and IPv6 is the exception to be handled if there is time left over. This shows up in small ways: rate limiting logic written around IPv4-style address blocks without an equivalent, well-considered concept for IPv6, or documentation that quietly assumes an IPv4 address format in its examples and leaves IPv6 handling as an implied afterthought.&lt;/p&gt;
&lt;p&gt;We built network-level quota tracking around both address families deliberately, not as an IPv6 patch bolted onto IPv4-first logic. Every network gets a shared free allowance, a /24 block for IPv4 addresses and a /48 block for IPv6 addresses, and both are treated as first class groupings rather than one being the primary design and the other an accommodation. The distinction between a /24 and a /48 is not arbitrary. It reflects how each address family is actually allocated by the regional internet registries responsible for handing out blocks, so the grouping means the same practical thing, a reasonably sized network, in both cases.&lt;/p&gt;
&lt;p&gt;Getting this wrong matters specifically for a location and IP data API, because the entire category of network-level and IP-based lookups depends on correctly parsing, matching, and rate limiting across both address formats. An API that quietly handles IPv6 as an edge case is more likely to produce inconsistent quota behavior, incorrect network groupings, or outright parsing failures for IPv6 traffic, at exactly the moment IPv6 adoption keeps growing and a meaningful share of real requests arrive over it rather than IPv4.&lt;/p&gt;
&lt;p&gt;Part of why this gets under-invested in industry-wide is that IPv4 traffic still represents a large share of total volume for a lot of services, which makes IPv6 edge cases feel like a low priority relative to the effort of getting them genuinely right. We think that reasoning discounts the trend line too heavily. A share of traffic that keeps growing is not well served by infrastructure that treats it as a permanent minority case, and the cost of fixing IPv6 handling properly only grows the longer a system&amp;#039;s core logic is built assuming IPv4 as the default.&lt;/p&gt;
&lt;p&gt;None of this is a dramatic claim. It is a request to take IPv6 as seriously as IPv4 in the actual design of rate limiting, quota tracking, and lookup logic, not just in a compliance checkbox that says an API technically accepts IPv6 addresses without a syntax error. Accepting an address format and handling it with the same care as the more common one are different achievements, and a lot of infrastructure across this industry has only really managed the first one.&lt;/p&gt;</content></entry>
<entry><title>Why address data should not require a sales call to test</title><link href="https://www.mygeocode.com/blog/why-address-data-should-not-require-a-sales-call-to-test/"/><id>https://www.mygeocode.com/blog/why-address-data-should-not-require-a-sales-call-to-test/</id><published>2026-09-13T21:47:00+00:00</published><updated>2026-09-13T21:47:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A geocoding API that gates real testing behind a sales conversation is asking a developer for trust before it has actually earned any of it.</summary><content type="html">&lt;p&gt;There is a specific kind of friction that shows up disproportionately around address data: a geocoding API with real coverage claims and a demo on its marketing page, but no way to actually run your own addresses through it without first filling out a form and waiting for a sales representative to reach out. The reasoning behind this gate is usually about qualifying leads or protecting a valuable dataset from casual scraping. The effect, regardless of the reasoning, is that a developer cannot answer the one question that actually matters, does this handle my addresses well, without first having a conversation that has nothing to do with the technical question itself.&lt;/p&gt;
&lt;p&gt;We do not gate testing behind a sales conversation. 2,500 requests a day, from any address, with no key required, is enough to run a real batch of your own representative addresses through the API and see what comes back, immediately, without scheduling anything. If a key is what you want next, getting one requires an email address, not a qualifying call about your expected volume or use case.&lt;/p&gt;
&lt;p&gt;The instinct to gate testing usually comes from treating evaluation traffic as a cost to be minimized rather than as the actual sales process working correctly. We think that gets the priorities backwards for a technical product specifically. A geocoding API is not a product most developers will trust based on a sales pitch or a demo built around cherry-picked example addresses. It is a product they trust after running their own messy, real-world address list through it and seeing how it actually behaves, including on the awkward cases that a curated demo would never include.&lt;/p&gt;
&lt;p&gt;This is also where we are careful to be honest about limits rather than let easy access imply more than it should. Being able to test forward geocoding, reverse geocoding, and autocomplete immediately, without a sales call, does not mean those specific endpoints are being presented as fully finished with verified accuracy across every address pattern. It means you get to find out directly, on your own data, what they actually do, rather than being told what they do by someone whose job is to close the conversation with a signed contract.&lt;/p&gt;
&lt;p&gt;A sales call has a legitimate place for genuinely large commitments where a direct conversation about specific needs is useful to both sides. It should not be the gate standing between a developer and the basic question of whether an API&amp;#039;s address handling is good enough for their use case. That question deserves a direct answer, from the API itself, on the first afternoon someone decides to find out, not after a scheduled call that happens sometime next week.&lt;/p&gt;
&lt;p&gt;We would rather earn a large account the same way we earn a small one: by letting the product answer the question directly. If the address handling holds up on your own real, messy list, that is a better argument for a bigger commitment than anything a sales conversation could say on its behalf.&lt;/p&gt;</content></entry>
<entry><title>The real cost of a provider&#039;s free tier changing overnight</title><link href="https://www.mygeocode.com/blog/the-real-cost-of-a-provider-s-free-tier-changing-overnight/"/><id>https://www.mygeocode.com/blog/the-real-cost-of-a-provider-s-free-tier-changing-overnight/</id><published>2026-09-13T10:44:00+00:00</published><updated>2026-09-13T10:44:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A free tier that gets cut without warning does not just cost the provider goodwill. It breaks whatever the customer built on top of an assumption that was never guaranteed.</summary><content type="html">&lt;p&gt;A free tier gets treated, correctly or not, as a stable foundation. A developer builds a small tool, a hobby project, or an early prototype of a real product on top of a provider&amp;#039;s free allowance, and that allowance quietly becomes load-bearing: the assumption baked into decisions about architecture, about whether to add a payment step at all, about how much the project is worth investing further time into. When a provider cuts that free tier overnight, tightens it substantially, or replaces it with a much smaller allowance, everything built on the old assumption breaks at once, with no warning and often no path to fix it except an unplanned, immediate purchase decision.&lt;/p&gt;
&lt;p&gt;This kind of change is usually defensible from the provider&amp;#039;s side: free tiers cost real money to run, usage patterns shift, and a company reserves the right to adjust terms. The cost of that change, though, does not land evenly. The provider absorbs a policy adjustment. The customer absorbs a broken integration, sometimes in production, sometimes affecting their own customers downstream, with no notice period to plan around.&lt;/p&gt;
&lt;p&gt;We think a provider offering a free tier takes on an implicit obligation that goes beyond the legal terms of service: if that allowance is going to change substantially, customers relying on it deserve enough notice to adjust before the change takes effect, not after. This is part of why our free allowance, 2,500 requests a day from any address plus 2,500 more per key, counted per network, is not something we treat as a temporary promotional hook subject to being pulled once it has served its marketing purpose. It is a stated part of the pricing model, not bait for an eventual bait and switch.&lt;/p&gt;
&lt;p&gt;There is a broader pattern worth naming here: a free tier used purely as an acquisition tactic tends to get adjusted once the acquisition goal has been met, because its only job was ever to attract signups, and once a critical mass of signups has occurred, the incentive to keep it generous weakens. A free tier treated as a permanent part of the pricing structure, sized based on what a provider can sustainably offer indefinitely rather than what looks maximally attractive on a landing page, does not carry that same incentive to shrink later, because it was never sized past what the provider intended to keep offering.&lt;/p&gt;
&lt;p&gt;None of this is a promise that no pricing detail will ever change. It is a statement about what kind of change is fair to make without warning and what kind is not. A price increase on paid usage, announced in advance, is a normal business decision. Quietly gutting the free allowance that hobby projects and early prototypes were built on, without warning, treats those projects as expendable, which is a strange way to treat the exact users most likely to become tomorrow&amp;#039;s paying customers if the free tier had just stayed put long enough for that project to grow into one.&lt;/p&gt;</content></entry>
<entry><title>Why we would rather lose a sale than hide a limit in fine print</title><link href="https://www.mygeocode.com/blog/why-we-would-rather-lose-a-sale-than-hide-a-limit-in-fine-print/"/><id>https://www.mygeocode.com/blog/why-we-would-rather-lose-a-sale-than-hide-a-limit-in-fine-print/</id><published>2026-09-12T23:22:00+00:00</published><updated>2026-09-12T23:22:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A customer who signs up not understanding a limit is a customer who leaves angry later. Telling them up front costs a sale sometimes. It is still the better trade.</summary><content type="html">&lt;p&gt;There is a specific, tempting shortcut available to any company writing its own pricing page: describe the good parts prominently and let the limits live in a footnote, a support article three clicks away, or language vague enough that most readers will assume the more generous interpretation. It works, in the narrow sense that it converts more signups than a page that states every limit plainly up front. It also produces a predictable, later cost: a customer who discovers a limit the hard way, mid-integration or on an invoice, and now feels misled rather than simply informed.&lt;/p&gt;
&lt;p&gt;We would rather take the smaller number of signups that comes from stating limits clearly than the larger number that comes from letting people sign up without fully understanding what they are getting. The free allowance is 2,500 requests a day, counted per network and shared between keyless and keyed use from that network. That is a genuinely useful number for evaluation and small-scale use, and it is also, plainly, a limit. Saying so directly, rather than emphasizing &amp;quot;free&amp;quot; and leaving the ceiling for someone to discover through a failed request, is the version of honesty that costs us something in the short term.&lt;/p&gt;
&lt;p&gt;The trade only looks bad if you measure success purely in signup counts. Measured over the life of a customer relationship, it looks different. A customer who understood the limits before committing and chose to proceed anyway is a customer who is not going to feel surprised or deceived later, because nothing about their situation changed between signup and the moment they actually hit a threshold. A customer who signed up under a vaguer impression, and then discovers the real ceiling once it affects them, has a legitimate grievance, and legitimate grievances turn into public complaints, refund requests, and reputational cost that outlasts the value of the signup that caused them.&lt;/p&gt;
&lt;p&gt;This same logic applies to why quota headers exist on every response rather than only in account dashboard, why rate limits are published as real numbers in the &lt;a href=&quot;/docs/rate-limits/&quot;&gt;documentation&lt;/a&gt; instead of described vaguely, and why the Unlimited key is actually unlimited rather than unlimited with an undisclosed soft cap. Each of these is a place where the vaguer, more generous-sounding version would probably convert slightly better on first impression, and the honest version is the one we chose anyway.&lt;/p&gt;
&lt;p&gt;We do not think this makes us unusually virtuous. It is closer to a bet about what kind of company survives its own customers actually using the product at scale, for years, rather than just signing up once. A pricing page optimized purely to maximize signups treats the signup as the finish line. We think the signup is closer to the starting line, and the fine print you did not read is exactly the part of the relationship that determines whether the years after signup go well.&lt;/p&gt;</content></entry>
<entry><title>What &quot;enterprise-grade&quot; usually means in this industry</title><link href="https://www.mygeocode.com/blog/what-enterprise-grade-usually-means-in-this-industry/"/><id>https://www.mygeocode.com/blog/what-enterprise-grade-usually-means-in-this-industry/</id><published>2026-09-12T10:17:00+00:00</published><updated>2026-09-12T10:17:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Enterprise-grade often just means the real price and the real usage limits are hidden behind a private sales call instead of a public pricing page.</summary><content type="html">&lt;p&gt;&amp;quot;Enterprise-grade&amp;quot; is one of those labels that sounds like a technical claim and is usually a commercial one. It rarely specifies a particular uptime guarantee, a particular support response time, or a particular capacity commitment that a customer could hold the provider to. What it reliably signals is that the actual price, and often the actual limits, are not on the pricing page at all. They are behind a form that leads to a sales call, where the number you get depends on how the conversation goes rather than on a rate published for everyone to see.&lt;/p&gt;
&lt;p&gt;We think this pattern deserves more skepticism than it usually gets. A pricing page that lists a self-serve tier clearly and then routes anything larger to &amp;quot;contact sales&amp;quot; is not necessarily hiding something sinister, but it is choosing opacity at exactly the point where a customer has the most at stake: a large-scale commitment. The customers with the most reason to need a clear, comparable number are the ones being asked to negotiate for it individually instead.&lt;/p&gt;
&lt;p&gt;My Geocode has one pricing structure regardless of scale: 2,500 free requests a day from any address, prepaid credit at €0.0001 per request beyond that, or a flat €50 a month for an Unlimited key. There is no separate enterprise tier with a different, undisclosed rate for larger customers, because we do not think usage volume by itself justifies a different price per request. The cost of serving a lookup does not change based on how large the customer sending it happens to be.&lt;/p&gt;
&lt;p&gt;Part of the appeal of an &amp;quot;enterprise-grade&amp;quot; sales-gated tier, from a provider&amp;#039;s perspective, is that it allows charging different customers different amounts for the same service based on what each one is willing to pay, rather than what the service actually costs to provide. That is a defensible business strategy in plenty of industries. We do not think it fits well with infrastructure that is supposed to be predictable and boring, the two qualities you actually want from something your product depends on every time a request goes out.&lt;/p&gt;
&lt;p&gt;None of this means every large customer needs to be treated identically to a hobbyist project. A big user of Unlimited keys or heavy prepaid credit is a bigger, more important relationship for us than a small keyless integration, and that can reasonably come with more direct support attention. What it should not come with is a different published rate per request, arrived at through negotiation rather than through a formula anyone could calculate on their own. If enterprise-grade is going to mean anything specific, it should describe a real technical or support commitment, not act as a polite label for a price that only exists after a phone call.&lt;/p&gt;</content></entry>
<entry><title>Why account-level and network-level quotas should both exist</title><link href="https://www.mygeocode.com/blog/why-account-level-and-network-level-quotas-should-both-exist/"/><id>https://www.mygeocode.com/blog/why-account-level-and-network-level-quotas-should-both-exist/</id><published>2026-09-11T23:34:00+00:00</published><updated>2026-09-11T23:34:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>An account-level quota tracks who you are. A network-level quota tracks where your traffic actually comes from. A serious system needs both.</summary><content type="html">&lt;p&gt;An account-level quota answers a simple question: how much has this specific key used. It is the natural first thing to track, and it is not enough on its own, because a key is just a credential, and credentials can be multiplied. Someone determined to exceed an account-level limit can often just create another account, generate another key, and start a fresh quota, unless something else is tracking a dimension that does not reset just because a new credential was issued.&lt;/p&gt;
&lt;p&gt;That is what network-level quotas are for. Every network, one /24 block for IPv4 addresses or one /48 block for IPv6, gets a shared 2,500 request free allowance a day, counted across both keyless traffic and any keys registered from that network. An account-level limit alone would let someone generate new keys indefinitely to keep resetting their free allowance. A network-level limit closes that specific gap, because it is tracking where the traffic is actually coming from, not just which credential happened to be attached to it.&lt;/p&gt;
&lt;p&gt;Neither measure alone is sufficient, and it is worth being specific about what each one protects against, since they solve different problems. Account-level tracking protects against a single credential being used far beyond what it should be, which matters for billing accuracy and for catching a leaked key being used somewhere it should not be. Network-level tracking protects against the free allowance specifically being multiplied through repeated signups, which is a different failure mode that account-level tracking alone cannot see, since each new account looks perfectly normal in isolation.&lt;/p&gt;
&lt;p&gt;Running both together does create a legitimate complication: multiple genuine users sharing a network, such as a company behind a small number of public IP addresses, could in theory bump into a network-level ceiling that has nothing to do with any individual user&amp;#039;s actual usage. We handle this with rolling IP slots, a fixed number of distinct addresses a key can be used from, and quota headers that show exactly how many of those slots are in use against the limit, so a legitimate shared network can see its real standing rather than hitting an opaque wall with no explanation.&lt;/p&gt;
&lt;p&gt;We think this is a case where the simpler design, tracking one dimension only, would actually be worse for honest users, not just less protective against abuse. A network-only limit would penalize an account for other unrelated activity on the same network. An account-only limit would leave the free allowance open to being multiplied indefinitely by anyone willing to create enough accounts. Running both, with visibility into each through response headers, is more moving parts, but it is the version that actually protects what a free allowance is supposed to protect without quietly punishing the people using it as intended.&lt;/p&gt;</content></entry>
<entry><title>The case for keeping a public status page honest</title><link href="https://www.mygeocode.com/blog/the-case-for-keeping-a-public-status-page-honest/"/><id>https://www.mygeocode.com/blog/the-case-for-keeping-a-public-status-page-honest/</id><published>2026-09-11T11:13:00+00:00</published><updated>2026-09-11T11:13:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A status page that always shows green, even during an outage, is not reassuring at all. It is evidence the page is decorative rather than operational.</summary><content type="html">&lt;p&gt;A status page exists to answer one specific question quickly: is the thing I depend on working right now, and if not, does the provider know about it yet. That is a narrow, useful purpose, and it only works if the page reflects reality closely enough to trust on the day it actually matters, which is the day something is broken. A status page that has shown all green for two years straight is either describing a genuinely flawless system, which is rare, or it is describing a page that gets updated on a schedule that has little to do with what customers are actually experiencing.&lt;/p&gt;
&lt;p&gt;The value of a status page is almost entirely concentrated in the moments it is least convenient to update honestly: during an active incident, when the instinct is to wait and see if it resolves quickly before committing to a public acknowledgment. That instinct is understandable and it is also exactly backwards from what makes a status page useful. A developer checking a status page during an outage on their own end wants to know, as early as possible, whether the problem is on their side or the provider&amp;#039;s. A page that waits to confirm an incident until it is fully understood and resolved answers that question too late to be worth much.&lt;/p&gt;
&lt;p&gt;We think the honest approach is to treat a status page as an operational tool rented out to customers, not a marketing surface. That means posting a real incident when a real incident is happening, even before every detail is known, and updating it as the picture becomes clearer, rather than holding the page green until a clean, fully resolved summary is ready to publish. A rough, early acknowledgment is more useful to someone debugging their own system in real time than a polished, delayed one.&lt;/p&gt;
&lt;p&gt;This connects to something we think about across the whole product, not just incident communication: giving developers information they can act on, as close to real time as possible. Quota headers on every response exist for the same reason a status page should be honest during an incident. Both are about not making someone wait until after the fact to learn something that would have changed what they did in the moment.&lt;/p&gt;
&lt;p&gt;A status page with an occasional yellow or red entry on it is not a mark against the provider. It is evidence the page is actually connected to something real. The page that should worry a prospective customer more is the one that never shows a blemish at all, because a system with genuinely zero incidents over a meaningful span of time is rare enough that its absence from the page usually says more about the page than about the system.&lt;/p&gt;</content></entry>
<entry><title>Why webhook-only APIs quietly exclude batch users</title><link href="https://www.mygeocode.com/blog/why-webhook-only-apis-quietly-exclude-batch-users/"/><id>https://www.mygeocode.com/blog/why-webhook-only-apis-quietly-exclude-batch-users/</id><published>2026-09-10T23:44:00+00:00</published><updated>2026-09-10T23:44:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A webhook works well for one request at a time. It works badly for a script that just wants to send a thousand lookups and wait for a thousand answers.</summary><content type="html">&lt;p&gt;A webhook makes sense for an event you cannot predict the timing of: a payment clearing, a shipment status changing, something happening on the provider&amp;#039;s side that your system needs to react to whenever it occurs. It makes much less sense as the only way to get an answer to a question you asked directly and expect a direct answer to, like resolving an address or looking up a time zone. Requiring a webhook endpoint just to receive the result of a synchronous lookup pushes real infrastructure work onto a customer who might just want to run a script, wait for a response, and move on.&lt;/p&gt;
&lt;p&gt;This becomes a bigger problem specifically for batch and bulk use cases. A developer running a one-off script to resolve a list of addresses from a spreadheet does not want to stand up a webhook receiver, handle retries if their endpoint is briefly unreachable, and correlate incoming webhook payloads back to the original requests, all to get answers that could have come back directly in the response to the call that asked for them. Webhook-only delivery for this kind of task adds an entire layer of infrastructure to a task that should be a single request and a single response.&lt;/p&gt;
&lt;p&gt;We treat lookups, including batch and bulk ones, as synchronous by default: you send the request, you get the answer back directly, whether that request contains one item or a thousand. Nothing about using a batch endpoint requires standing up a public-facing receiver just to collect results. A script, a cron job, or a one-off command line tool can call the endpoint and use the response immediately, the same way a single lookup would work.&lt;/p&gt;
&lt;p&gt;Webhook-only design tends to come from an architecture built around asynchronous processing on the provider&amp;#039;s side, where a large batch job actually takes meaningful time to complete internally, and a webhook is genuinely the more natural way to signal completion. That is a legitimate pattern for some kinds of large-scale or heavily queued processing. It becomes a problem when it is the only option offered, forcing every use case, including ones that would rather just wait a moment and get an answer directly, into an architecture designed for a different, slower kind of workload.&lt;/p&gt;
&lt;p&gt;We are not against webhooks existing as an option for genuinely long-running or asynchronous work. We are against making them mandatory for tasks that do not need to be asynchronous at all. A script that wants to send a thousand lookups and get a thousand answers back should be able to do exactly that, in one call and one response, without first building infrastructure to receive a callback for a task that a synchronous request would have handled just as well, with a lot less code involved.&lt;/p&gt;</content></entry>
<entry><title>What coordinate precision marketing gets backwards</title><link href="https://www.mygeocode.com/blog/what-coordinate-precision-marketing-gets-backwards/"/><id>https://www.mygeocode.com/blog/what-coordinate-precision-marketing-gets-backwards/</id><published>2026-09-10T11:24:00+00:00</published><updated>2026-09-10T11:24:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A response with fifteen decimal places of latitude looks precise. It is not accurate just because it has more digits than the method can actually support.</summary><content type="html">&lt;p&gt;Latitude and longitude returned to fifteen decimal places look impressively exact. The fifteenth decimal place of a coordinate corresponds to a distance smaller than an atom, which should be an immediate signal that the precision on display has nothing to do with the accuracy of the underlying match. A geocoding result derived from a postal boundary centroid, a rooftop match, or a rough area estimate does not become more accurate because the response carries more digits after the decimal point. It just carries more digits.&lt;/p&gt;
&lt;p&gt;This distinction, precision versus accuracy, gets blurred constantly in how location data gets presented. Precision is how many digits a number has. Accuracy is how close that number actually is to the real location. A coordinate can be extremely precise and substantially wrong, and a response format that leads with a long decimal string invites the reader to assume the two are the same thing, when they are not related at all beyond the fact that one can disguise the absence of the other.&lt;/p&gt;
&lt;p&gt;We think the more honest thing a response can do is describe what kind of match actually produced the coordinate, rather than relying on decimal length to imply a level of confidence the underlying method may not support. A rooftop-level match and a city-centroid fallback are different in kind, not just in decimal precision, and collapsing that difference into &amp;quot;more decimal places means better&amp;quot; hides exactly the information a developer needs to decide whether a given result is good enough for their use case, whether that is drawing a pin on a map or routing a delivery vehicle.&lt;/p&gt;
&lt;p&gt;This connects directly to why we are careful about how we describe our own forward geocoding, reverse geocoding, and autocomplete endpoints. It would be easy to return coordinates with a long decimal tail and let that stand in for a confidence claim we are not prepared to make plainly. We would rather be specific about what the endpoint returns and let the actual match information speak for itself than lean on decimal formatting to imply more than the underlying data justifies.&lt;/p&gt;
&lt;p&gt;There is a practical takeaway here for anyone consuming a geocoding API, not just for how we chose to build ours: decimal places in a coordinate are not evidence of quality. What matters is whether the response tells you, in plain terms, what was actually matched, at what level of specificity, so you can decide for yourself whether that specific answer is good enough for the decision you are about to make with it. A long string of digits after the decimal point answers a question about formatting. It does not answer the question that actually matters, which is whether the point in the world that those digits describe is the right one.&lt;/p&gt;</content></entry>
<entry><title>Why we publish our error codes instead of hiding them</title><link href="https://www.mygeocode.com/blog/why-we-publish-our-error-codes-instead-of-hiding-them/"/><id>https://www.mygeocode.com/blog/why-we-publish-our-error-codes-instead-of-hiding-them/</id><published>2026-09-09T23:18:00+00:00</published><updated>2026-09-09T23:18:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>An undocumented error code turns every failed request into a guessing game. Publishing the list is a small thing that saves real debugging time.</summary><content type="html">&lt;p&gt;A failed API request is already a bad moment in someone&amp;#039;s day. It gets worse when the error code that comes back is not explained anywhere, and the developer debugging it has to guess whether a 400 means a malformed parameter, a missing required field, or something entirely different that happens to share the same status code as three other unrelated problems. An undocumented error is not just an inconvenience. It converts a five-minute fix into an open-ended investigation, sometimes ending in a support ticket that could have been avoided by reading a page that should have existed.&lt;/p&gt;
&lt;p&gt;We publish our error codes plainly in the &lt;a href=&quot;/docs/errors/&quot;&gt;errors documentation&lt;/a&gt;, listing what each one actually means and what commonly causes it, alongside the &lt;a href=&quot;/docs/authentication/&quot;&gt;authentication&lt;/a&gt; and &lt;a href=&quot;/docs/rate-limits/&quot;&gt;rate limits&lt;/a&gt; pages that describe the other ways a request can fail. The goal is that when something goes wrong, the answer is one page away, not a guess based on general HTTP status code conventions that may or may not map cleanly onto what our system specifically did.&lt;/p&gt;
&lt;p&gt;Hiding error details, even unintentionally through thin documentation, sometimes comes from a reasonable-sounding instinct: exposing exactly why a request failed could theoretically help someone probing an API for weaknesses. In practice, this concern rarely holds up against the actual cost. The overwhelming majority of people encountering an error code are legitimate developers trying to fix their own integration, not adversaries mapping an attack surface. Optimizing error documentation around the rare bad actor, at the cost of clarity for everyone else, gets the tradeoff backwards.&lt;/p&gt;
&lt;p&gt;There is also a design discipline benefit to publishing error codes clearly: it forces internal consistency. If every error code has to be documented with a plain explanation, it becomes much harder to accumulate a pile of ad hoc, overlapping error conditions that only the original engineer who wrote them fully understands. Writing the documentation is also, quietly, a form of code review on the error handling itself, because an error that is hard to explain clearly is often a sign the underlying condition was not well thought through in the first place.&lt;/p&gt;
&lt;p&gt;Quota-related failures get a related treatment through response headers rather than error codes alone. Every response carries your quota limit, usage, remaining free allowance, network usage, remaining credit, and reset time, so a request that fails due to quota is not a mystery status code at all. It is a number you could have checked before sending the request, and one you can read directly from the response that failed.&lt;/p&gt;
&lt;p&gt;None of this eliminates the frustration of a failed request. It just means the frustration should end at the documentation, with an actual answer, rather than continuing into a support queue or a guessing game across old forum posts about what a status code from an entirely different API might have meant in a similar-sounding situation.&lt;/p&gt;</content></entry>
<entry><title>The trouble with data that&#039;s accurate on launch day only</title><link href="https://www.mygeocode.com/blog/the-trouble-with-data-that-s-accurate-on-launch-day-only/"/><id>https://www.mygeocode.com/blog/the-trouble-with-data-that-s-accurate-on-launch-day-only/</id><published>2026-09-09T10:04:00+00:00</published><updated>2026-09-09T10:04:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A dataset announced with pride and never revisited degrades quietly. Borders shift, postal systems change, and time zone rules get amended by governments that do not send a press release.</summary><content type="html">&lt;p&gt;A dataset is easiest to be proud of on the day it launches. It has been checked, cleaned, and validated against whatever sources were available at the time, and the announcement can honestly claim strong coverage and accuracy, because at that specific moment, it earned the claim. The trouble is that almost nothing about geography stays fixed for long. Administrative boundaries shift. Postal authorities redraw or reissue codes. Governments amend daylight saving rules, sometimes with very little notice. A dataset that was accurate on launch day and has not been actively maintained since is not the same dataset anymore, even though it may still be marketed with the same confidence.&lt;/p&gt;
&lt;p&gt;The IANA time zone database is a useful example of how this actually gets handled well: it exists specifically because time zone rules keep changing, and it gets updated as those changes happen, by people whose job is tracking exactly that kind of shift. A geocoding or location API that draws on a source like this and keeps pulling updates from it is doing something meaningfully different from a provider that built a one-time snapshot years ago and has been serving it, lightly patched, ever since.&lt;/p&gt;
&lt;p&gt;We think this distinction, ongoing maintenance versus a one-time build, deserves more attention than it usually gets in how location data products are marketed. A launch announcement can claim broad country coverage and it will be true. What it cannot promise, on its own, is that the coverage stays true two years later, after boundary changes, postal reorganizations, and time zone rule amendments that happened quietly in the meantime, with no reason for a customer to know to check.&lt;/p&gt;
&lt;p&gt;This is part of why we treat time zone, elevation, and IP data as the parts of our product we describe most concretely, since these are areas where the underlying reference data, the kind of source the IANA database represents for time zones, gets maintained on an ongoing basis by design, not by a provider&amp;#039;s internal update schedule alone. It is also why we are careful about overstating forward geocoding, reverse geocoding, and autocomplete as fully finished with verified accuracy: address data specifically has enormous regional variability in how well it gets maintained, and a confident-sounding claim about it deserves more scrutiny than the claim itself usually invites.&lt;/p&gt;
&lt;p&gt;A dataset&amp;#039;s age is not a defect by itself. A well-maintained dataset from five years ago that has been kept current is more trustworthy than a fresh one that will not be revisited again until the next redesign. What matters is whether a provider treats data maintenance as a continuous obligation or a one-time project that was finished when the marketing page went live. The honest way to judge that is not the launch announcement. It is what a provider does, quietly, in the years after it.&lt;/p&gt;</content></entry>
<entry><title>Why batch pricing should match single-request pricing</title><link href="https://www.mygeocode.com/blog/why-batch-pricing-should-match-single-request-pricing/"/><id>https://www.mygeocode.com/blog/why-batch-pricing-should-match-single-request-pricing/</id><published>2026-09-08T22:42:00+00:00</published><updated>2026-09-08T22:42:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A thousand lookups sent one at a time and a thousand lookups sent as a batch are the same amount of work. The price should not depend on how they were packaged.</summary><content type="html">&lt;p&gt;It is tempting to think of a batch endpoint as a bulk discount opportunity, the same instinct that makes buying a large pack of something feel cheaper per unit than buying pieces individually. That instinct does not actually apply to API requests the way it applies to physical goods. A batch of a thousand address lookups requires the same thousand individual lookups whether they arrive in one connection or a thousand separate ones. There is no economy of scale hiding in the fact that they arrived together, because the expensive part, resolving each lookup, is identical either way.&lt;/p&gt;
&lt;p&gt;We price batch and bulk requests exactly the same, per item, as single requests. A thousand-item batch call counts as a thousand requests against your free allowance or your prepaid credit, at the same €0.0001 per request as calling the endpoint a thousand separate times, or covered the same way under an Unlimited key. There is no separate, cheaper batch rate, because there is no separate, cheaper amount of underlying work being done.&lt;/p&gt;
&lt;p&gt;Some providers do offer a bulk discount, and the appeal for a customer is obvious: send more, pay less per unit. The reasoning behind that discount is worth questioning rather than just welcoming. If the marginal cost of serving a lookup is genuinely close to constant, the way it is for most geocoding, IP, and time zone lookups, a bulk discount is not passing along a real efficiency gain. It is a pricing decision to charge more to smaller customers to subsidize a lower rate for larger ones, dressed up as a reward for volume rather than what it actually is, a cross-subsidy.&lt;/p&gt;
&lt;p&gt;Flat, item-based pricing avoids that cross-subsidy entirely. A customer sending a hundred requests a day and a customer sending a hundred thousand pay exactly the same rate per request, once both are past the free allowance. Neither is subsidizing the other&amp;#039;s usage. This also keeps the free allowance itself fair: a batch call still consumes the same 2,500-request daily allowance at the same one-request-per-item rate, so batching cannot be used to quietly stretch free usage further than an equivalent number of single calls would.&lt;/p&gt;
&lt;p&gt;We recognize batching is genuinely useful for reasons that have nothing to do with price: fewer round trips, less connection overhead, simpler code for processing a large, known set of lookups at once. Those are real engineering benefits and worth using batch endpoints for on their own merits. What batching should not become is a mechanism for making the same total amount of work look cheaper on an invoice than it actually is. A thousand lookups cost what a thousand lookups cost, and the price should say so plainly, regardless of how they were packaged into requests.&lt;/p&gt;</content></entry>
<entry><title>What a free tier is actually for</title><link href="https://www.mygeocode.com/blog/what-a-free-tier-is-actually-for/"/><id>https://www.mygeocode.com/blog/what-a-free-tier-is-actually-for/</id><published>2026-09-08T10:52:00+00:00</published><updated>2026-09-08T10:52:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A free tier is not a discount, and it is not bait for a sales call. It is the smallest useful amount of a product a developer needs to find out if it fits.</summary><content type="html">&lt;p&gt;A free tier gets designed for one of two very different reasons, and it is usually obvious after a few minutes of use which one a given provider chose. One version exists to let a developer genuinely evaluate a product: enough volume to build a real integration, run it against real data, and decide whether it is worth paying for. The other version exists to create a taste just large enough to generate interest and just small enough to force an upgrade decision almost immediately, functioning less like an evaluation tool and more like the first page of a pitch.&lt;/p&gt;
&lt;p&gt;Ours is meant to be the first kind. 2,500 requests a day from any address, no key needed, and another 2,500 a day once you add a key, counted per network and shared between keyless and keyed use from that network. That is enough to build and test a real integration, not a token amount that runs out during the first afternoon of trying the API and leaves you making a purchase decision before you have learned anything.&lt;/p&gt;
&lt;p&gt;The distinction matters because a free tier sized as bait produces a specific, bad kind of decision-making. A developer who runs out of free requests in the first hour is not deciding to upgrade because the product proved its value. They are deciding whether to keep spending time on an evaluation that got cut short, often before they even reached the parts of the integration that would reveal whether the data quality and response shape genuinely fit their use case. That is not a real evaluation. It is a truncated one, dressed up as a free trial.&lt;/p&gt;
&lt;p&gt;A free tier sized for genuine evaluation costs the provider more, in the direct sense that some meaningful fraction of that usage will never convert into revenue. We think that cost buys something worth having: a customer who upgrades because they actually tested the product and it worked, not because a countdown or a request cap forced the decision before the testing was finished. The conversion that follows from real evaluation tends to be a more durable one, because it is based on the product rather than on running out of runway to keep evaluating it.&lt;/p&gt;
&lt;p&gt;There is a second, quieter purpose a generous free tier serves: it covers small, permanent, low-volume use cases without ever requiring a paid account at all. A personal project, a small nonprofit tool, a student assignment, none of these need to become a customer just to keep working within a reasonable daily allowance. A free tier that only exists to expire is not built to serve that use case. Ours is, on purpose, because not every legitimate use of an API needs to become a line item on someone&amp;#039;s monthly budget.&lt;/p&gt;</content></entry>
<entry><title>Why &quot;AI-powered geocoding&quot; claims deserve scrutiny</title><link href="https://www.mygeocode.com/blog/why-ai-powered-geocoding-claims-deserve-scrutiny/"/><id>https://www.mygeocode.com/blog/why-ai-powered-geocoding-claims-deserve-scrutiny/</id><published>2026-09-08T00:36:00+00:00</published><updated>2026-09-08T00:36:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>Calling a lookup AI-powered is a marketing choice more often than a technical disclosure. The question that matters is whether the answer is right, not what produced it.</summary><content type="html">&lt;p&gt;A geocoding feature described as AI-powered sounds more advanced than one described plainly as address matching. Whether that label reflects a meaningful technical difference or just a marketing decision made after the fact is usually impossible to tell from the outside, and that is exactly the problem. The label answers a question about vocabulary. It does not answer the question that actually matters to a developer deciding whether to trust the response: is the match correct, and how does it behave on the addresses that do not fit a clean pattern.&lt;/p&gt;
&lt;p&gt;We are cautious about this kind of language for our own endpoints, and skeptical of it when we see it elsewhere. A machine learning component genuinely can help with fuzzy matching, handling typos, or resolving ambiguous partial addresses more gracefully than a rigid rule-based lookup would. That is a real, useful thing a system can do. It is a different claim entirely from asserting that the resulting matches are therefore more accurate across the board, which is a claim that needs actual evidence specific to the addresses and regions a customer cares about, not an inference from the word AI on a features page.&lt;/p&gt;
&lt;p&gt;The core issue is that &amp;quot;AI-powered&amp;quot; describes a method, not an outcome. A method can be sophisticated and still produce a wrong answer, and a simpler method can be perfectly reliable for the cases it is built to handle. What a developer integrating a geocoding endpoint needs to know is the outcome: which address patterns are handled well, which are not, and what a low-confidence or ambiguous result looks like when it comes back. None of that is answered by the method label, however impressive it sounds.&lt;/p&gt;
&lt;p&gt;We are being deliberately careful in what we claim about our own forward geocoding, reverse geocoding, and autocomplete endpoints for this exact reason. We can describe what they do and how they are structured. We are not going to assert a specific, verified real-world accuracy figure as if it were an established fact, because doing that convincingly requires exactly the kind of rigorous, ongoing evaluation that a label alone does not substitute for, whether or not the label includes the word AI.&lt;/p&gt;
&lt;p&gt;None of this is an argument against machine learning techniques being used in geocoding. It is an argument against letting a technique become a substitute for a claim about results. If a method genuinely improves match quality, the way to demonstrate that is showing the improvement on real, representative cases, not naming the method and letting the reader assume the improvement follows automatically. A label is not evidence. It is, at best, a hint about where to look for evidence, and at worst, a way of skipping the part where evidence was supposed to come next.&lt;/p&gt;</content></entry>
<entry><title>The case for boring, stable API versioning</title><link href="https://www.mygeocode.com/blog/the-case-for-boring-stable-api-versioning/"/><id>https://www.mygeocode.com/blog/the-case-for-boring-stable-api-versioning/</id><published>2026-09-07T11:39:00+00:00</published><updated>2026-09-07T11:39:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>An exciting new API version is a migration project for everyone downstream of it. Boring, stable versioning is a feature, not a lack of ambition.</summary><content type="html">&lt;p&gt;A provider announcing a major new API version is usually announcing, to every customer with an existing integration, a project they did not ask for. Even a well-communicated breaking change means someone has to schedule time to read a migration guide, update request or response handling, test it, and deploy it, on a timeline set by the provider&amp;#039;s roadmap rather than by anything happening in that customer&amp;#039;s own product.&lt;/p&gt;
&lt;p&gt;We think API stability is worth treating as a design goal in its own right, not a lack of momentum. A response shape, once published, should keep meaning what it meant when a developer first built against it. New fields can be added as optional additions, the way elevation, IP threat, and network detail are opt-in extras layered onto standard responses rather than forced restructurings of them. What should not happen quietly is an existing field changing meaning, a status code being repurposed, or a shape being restructured under the same version number.&lt;/p&gt;
&lt;p&gt;Part of why breaking changes happen so often across this industry is that they are cheap for the provider and expensive for the customer, and the two sides rarely negotiate over that imbalance directly. Shipping a cleaner internal model is a legitimate engineering win for a provider&amp;#039;s own team. It becomes a burden the moment it forces every downstream integration to change in response, on a schedule the provider controls and the customer does not.&lt;/p&gt;
&lt;p&gt;This does not mean an API should never change. It means changes should be additive wherever possible, and where a genuine breaking change is unavoidable, it should be rare enough that a customer can trust the shape they built against will still work months or years later, not something they need to monitor a changelog to defend against. Stability is not the same as stagnation. It is a promise that today&amp;#039;s integration work does not have an expiration date attached to it that nobody told you about.&lt;/p&gt;
&lt;p&gt;There is a selfish reason for us to hold this position too, beyond customer goodwill. Every compatibility host we run depends on matching another provider&amp;#039;s shape faithfully over time, which only works if shapes, once matched, are worth relying on as stable targets. A company that treats its own API surface as disposable, to be redesigned whenever convenient, is a company whose compatibility guarantees are not really guarantees either. Stability has to be a habit that applies everywhere or it does not really apply anywhere.&lt;/p&gt;
&lt;p&gt;Boring is not a criticism here. A version of an API that still works exactly the way it did when you first integrated it, years later, is not evidence that nothing improved. It is evidence that improvements happened in ways that did not require you to notice them, which is the entire point of good versioning discipline.&lt;/p&gt;</content></entry>
<entry><title>Why we didn&#039;t build a browser SDK first</title><link href="https://www.mygeocode.com/blog/why-we-didn-t-build-a-browser-sdk-first/"/><id>https://www.mygeocode.com/blog/why-we-didn-t-build-a-browser-sdk-first/</id><published>2026-09-06T22:52:00+00:00</published><updated>2026-09-06T22:52:00+00:00</updated><category term="our-takes" label="Our takes"/><summary>A browser SDK for a server-side lookup mostly just moves your API key somewhere a visitor&#039;s browser can see it. That is not a convenience worth having.</summary><content type="html">&lt;p&gt;A browser SDK is an easy thing to ask for and a genuinely bad idea for a lot of what a geocoding or IP lookup API actually does. Resolving an IP address to a location is meaningful specifically because it happens on the server, where the request&amp;#039;s real origin is visible. Ship that same lookup into client-side JavaScript running in a visitor&amp;#039;s browser and you have not made the integration more convenient. You have moved an authenticated API key into the one place on the entire request path where anyone can open developer tools and read it.&lt;/p&gt;
&lt;p&gt;This is why we did not prioritize a browser SDK ahead of plain HTTP support and compatibility hosts. A key accepted as an X-API-Key header, a Bearer token, HTTP Basic auth, or a query parameter works the same on every host, called from wherever your server-side code already lives: a backend service, a serverless function, a batch job, anywhere the request already has a reason to originate from infrastructure you control rather than a browser tab you do not.&lt;/p&gt;
&lt;p&gt;IP geolocation specifically only makes sense server side. The entire value of the lookup comes from resolving the actual IP address making the request, which for most meaningful use cases, fraud checks, localization, analytics you control yourself rather than sell, needs to happen where that IP address is authoritative: your server, receiving the request directly, not a browser environment where the &amp;quot;IP&amp;quot; a client-side call would report is either irrelevant or trivially spoofable.&lt;/p&gt;
&lt;p&gt;Geocoding a typed address is less clearly server-only, and there is a real argument for wanting address autocomplete to feel responsive directly in a form, in the browser, without a round trip through your own backend first. We are not against that pattern existing eventually. We are against building it as the first and primary integration path, ahead of the plain server-side HTTP access that the majority of real use cases, checkout flows, shipping calculators, fraud checks, actually need and that does not require exposing a credential to the public.&lt;/p&gt;
&lt;p&gt;The broader pattern we are pushing back on is treating &amp;quot;ships a browser SDK&amp;quot; as a checkbox every API is expected to have, regardless of whether client-side access to that particular kind of data makes sense. For a lookup where the server-side context is the entire point, a browser SDK mostly just answers a marketing question, &amp;quot;does this look modern and convenient&amp;quot;, at the cost of a real security question, &amp;quot;where does this credential end up living.&amp;quot; We would rather answer the security question first and let convenience follow it, not the other way around.&lt;/p&gt;
&lt;p&gt;None of this rules out a lighter, browser-friendly tool eventually, scoped specifically to the cases where client-side use genuinely makes sense, like a form autocomplete that never needs your account&amp;#039;s real credential to function. What it should not be is the first thing we ask a customer to trust, ahead of the plain HTTP path that already covers the majority of real integrations safely.&lt;/p&gt;</content></entry>
</feed>
