16 ms·
Everything I know about good API design
- cyberax 1y ago> You should let people use your APIs with a long-lived API key. Sigh... I wish this were not true. It's a shame that no alternatives have emerged so far.
- TrueDuality 1y agoThere are other options that allow long-lived access with naturally rotating keys without OAuth and only a tiny amount of complexity increase that can be managed by a bash script. The refresh token/bearer token combo is pretty powerful and has MUCH stronger security properties than a bare API key.
- rahkiin 1y agoIf api keys do not need to ve stateless, every api key can become a refresh token with a full permission and validity lookup.
- marcosdumay 1y agoThis. The separation of a refresh cycle is an optimization done for scale. You don't need to do it if you don't need the scale. (And you need a really huge scale to hit that need.)
- maxwellg 1y agoRefresh tokens are only really required if a client is accessing an API on behalf of a user. The refresh token tracks the specific user grant, and there needs to be one refresh token per user of the client. If a client is accessing an API on behalf of itself (which is a more natural fit for an API Key replacement) then we can use client_credentials with either client secret authentication or JWT bearer authentication instead.
- TrueDuality 1y agoThat is a very specific form of refresh token but not the only model. You can just easily have your "API key" be that refresh token. You submit it to an authentication endpoint, get back a new refresh token and a bearer token, and invalidate the previous bearer token if it was still valid. The bearer token will naturally expire and if you're still using it, just use the refresh immediately, if its days or weeks later you can use it then. There doesn't need to be any OIDC or third party involved to get all the benefits of them. The keys can't be used by multiple simultaneous clients, they naturally expire and rotate over time, and you can easily audit their use (primarily due to the last two principles).
- 0x1ceb00da 1y ago> The refresh token/bearer token combo is pretty powerful and has MUCH stronger security properties than a bare API key I never understood why.
- TrueDuality 1y agoThe quick rundown of refresh token I'm referring to is: 1. Generate your initial refresh token for the user just like you would a random API key. You really don't need to use a JWT, but you could. 2. The client sends the refresh token to an authentication endpoint. This endpoint validates the token, expires the refresh token and any prior bearer tokens issued to it. The client gets back a new refresh token and a bearer token with an expiration window (lets call it five minutes). 3. The client uses the bearer token for all requests to your API until it expires 4. If the client wants to continue using the API, go back to step 2. The benefits of that minimal version: Client restriction and user behavior steering. With the bearer tokens expiring quickly, and refresh tokens being one-time use it is infeasible to share a single credential between multiple clients. With easy provisioning, this will get users to generate one credential per client. Breach containment and blast radius reduction. If your bearer tokens leak (logs being a surprisingly high source for these), they automatically expire when left in backups or deep in the objects of your git repo. If a bearer token is compromised, it's only valid for your expiration window. If a refresh token is compromised and used, the legitimate client will be knocked offline increasing the likelihood of detection. This property also allows you to know if a leaked refresh token was used at all before it was revoked. Audit and monitoring opportunities. Every refresh creates a logging checkpoint where you can track usage patterns, detect anomalies, and enforce policy changes. This gives you natural rate limiting and abuse detection points. Most security frameworks (SOC 2, ISO 27001, etc.) prefer time-limited credentials as a basic security control. Add an expiration time to refresh tokens to naturally clean up access from broken or no longer used clients. Example: Daily backup script. Refresh token's expiration window is 90 days. The backups would have to not run for 90 days before the token was an issue. If it was still needed the effort is low, just provision a new API key. After 90 days of failure you either already needed to perform maintenance on your backup system or you moved to something else without revoking the access keys.
- pixelatedindex 1y agoTo add on, are they talking about access tokens or refresh tokens? It can’t be just one token, because then when it expires you have to update it manually from a portal or go through the same auth process, neither of which is good. And what time frame is “long-lived”? IME access tokens almost always have a lifetime of one week and refresh tokens anywhere from 6 months to a year.
- rahkiin 1y agoInthink they are talking about refresh token or Api Keys like PATs. Some value you pass in a header and it just works. No token flow. And the key is valid for months and can be revoked
- cyberax 1y agoIf you're using APIs from third parties, the most typical authentication method is a static key that you stick in the "Authorization" HTTP header. OAuth flows are not at all common for server-to-server communications. In my perfect world, I would replace API keys with certificates and use mutual TLS for authentication.
- nostrebored 1y agoIn your perfect world, are you primarily the producer or consumer of the API? I hate mTLS APIs because they often mean I need to change how my services are bundled and deployed. But to your point, if everything were mTLS I wouldn’t care.
- cyberax 1y ago> In your perfect world, are you primarily the producer or consumer of the API? Both, really. mTLS deployment is the sticking point, but it's slowly getting better. AWS load balancers now support it, they terminate the TLS connection, validate the certificate, and stick it into an HTTP header. Google Cloud Platform and CloudFlare also support it.
- pixelatedindex 1y ago
- xtacy 1y agoAre there good public examples of well designed APIs that have stood the test of time?
- binaryturtle 1y agoI always thought the Amiga APIs with the tag lists were cool. You easily could extend the API/ABI w/o breaking anything at the binary level (assuming you made the calls accept tag lists as parameters to begin with, of course).
- pixl97 1y agoWhile the author doesn't seem to like version based APIs very much, I always recommend baking them in from the very start of your application. You cannot predict the future and chances are there will be some breaking change forced upon you by someone or something out of your control.
- claw-el 1y agoIf there is a breaking change forced upon in the future, can’t we use a different name for the function?
- deleted 1y ago[deleted]
- soulofmischief 1y agoA versioned API allows for you to ensure a given version has one way to do things and not 5, 4 of which are no longer supported but can't be removed. You can drop old weight without messing up legacy systems.
- CharlesW 1y agoYou could, but it just radically increases complexity in comparison to "version" knob in a URI, media type, or header.
- Bjartr 1y agoSee the many "Ex" variations of many functions in the Win32 API for examples of exactly that!
- jahewson 1y ago/api/postsFinalFinalV2Copy1-2025(1)ExtraFixed
- pixl97 1y agoDiscoverability. /v1/downloadFile /v2/downloadFile Is much easier to check for a v3 then /api/downloadFile /api/downloadFileOver2gb /api/downloadSignedFile Etc. Etc.
- deleted 1y ago[deleted]
- claw-el 1y ago> However, a technically-poor product can make it nearly impossible to build an elegant API. That’s because API design usually tracks the “basic resources” of a product (for instance, Jira’s resources would be issues, projects, users and so on). When those resources are set up awkwardly, that makes the API awkward as well. One issue I have with weird resources are those that feel like unnecessary abstraction. It makes it hard for the human to read and understand intuitively, especially someone new to these set of APIs. Also, it makes it so much harder to troubleshoot during an incident.
- frabonacci 1y agoThe reminder to "never break userspace" is gold and often overlooked.. ahem Spotify, Reddit and Twitter come to mind.
- runroader 1y agoI think the only thing here that I don't agree with is that internal users are just users. Yes, they may be more technical - or likely other programmers, but they're busy too. Often they're building their own thing and don't have the time or ability to deal with your API churning. If at all possible, take your time and dog-food your API before opening it up to others. Once it's opened, you're stuck and need to respect the "never break userspace" contract.
- devmor 1y agoI think versioning still helps solve this problem. There’s a lot of things you can do with internal users to prevent causing a burden though - often the most helpful one is just collaborating on the spec and making the working copy available to stakeholders. Even if it’s a living document, letting them have a frame of reference can be very helpful (as long as your office politics prevent them from causing issues for you over parts in progress they do not like.)
- Supermancho 1y agoWith internal users, you likely have instrumentation that allows you to contact and have those users migrate. You can actually sunset api versions, making API versioning an attractive solution. I've both participated in API versioning and observed it employed in organizations that don't use it by default as a matter of utility.
- scott_w 1y agoA big difference is you can tell internal users to update or else. It’s not free and should be reserved for good business reasons, but it can happen on a shorter time frame as you have the internal organisation to enforce it. It’s not really an option in the same way with end users or customers, as they aren’t part of your organisation, by definition.
- cyberax 1y agoI'm a bit of a different opinion on API versioning, but I can see the argument. I definitely disagree about idempotency: it's NOT optional. You don't have to require idempotency tokens for each request, but there should be an option to specify them. Stripe API clients are a good example here, they automatically generate idempotency tokens for you. Things that's missing from this list but that were important for me at some points: 1. Deadlines. Your API should allow to specify the deadline after which the request is no longer going to matter. The API implementation can use this deadline to cancel any pending operations. 2. Closely related: backpressure and dependent services. Your API should be designed to not overload its own dependent services with useless retries. Some retries might be useful, but in general the API should quickly propagate the error status back to the callers. 3. Static stability. The system behind the API should be designed to fail static, so that it retains some functionality even if the mutating operations fail.
- dwattttt 1y agoThe reminder to "never break userspace" is good, but people never bring up the other half of that statement: "we can and will break kernel APIs without warning". It illustrates that the reminder isn't "never change an API in a way that breaks someone", it's the more nuanced "declare what's stable, and never break those".
- chubot 1y agoYeah, famously there is no stable public driver API for Linux, which I believe was the motivation for Google’s Fuschia OS So Linux is opinionated in both directions - towards user space and toward hardware - but in the opposite way
- matheusmoreira 1y agoIt's not just opinionation though. It's the kernel's leverage against the people who would keep their modules out of the git tree instead of contributing them. Those people literally get left behind and they are forced to pay maintainers to chase a continuously moving target. The solution to that is to contribute the code.
- delta_p_delta_x 1y agoEven if the kernel doesn't break userspace, GNU libc does, all the time, so the net effect is that Linux userspace is broken regardless of the kernel maintainers' efforts. Put simply, programs and libraries compiled on/for newer libc are ABI-incompatible or straight-up do not run on older libc, so everything needs to be upgraded in lockstep. It is a bit ironic and a little funny that Windows solved this problem a couple decades ago with redistributables.
- Retr0id 1y agootoh staticly-linked executables are incredibly stable - it's nice to have that option.
- delta_p_delta_x 1y ago
- zahlman 1y agoAnyone else old enough to remember when "API" also meant something that had nothing to do with sending and receiving JSON over HTTP? In some cases, you could even make something that your users would install locally, and use without needing an Internet connection.
- drdaeman 1y agoI believe it’s pretty common to e.g. call libraries’ and frameworks’ user- (developer-) facing interface an API, like in “Python’s logging library has a weird-looking API”, so I don’t think API had eroded to mean only networked ones.
- mettamage 1y agoI never understood why libraries also had the word API. From my understanding a library is a set of functions specific to a certain domain, such as a statistics library, for example. Then why would you need the word API? You already know it’s a library. For end points it’s a bit different. You don’t know what are they or user facing or programmer facing. I wonder if someone has a good take on this. I’m curious to learn.
- shortrounddev2 1y agoTo me the API is the function prototypes. The DLL is the library
- dfee 1y agoTo use code, you need an interface. One for programming. Specifically to build an application. Why does the type of I/O boundary matter?
- mettamage 1y agoWouldn't the interface in C simply be called function headers? Why are we using the term API? It seems a word like "function signatures" would also make it clear (or just signatures or headers). Maybe I just don't understand what the word interface means other than the GUI version of it. What's an interface in the analogue world? [2] By the way, one person downvoted me. To that person: it's fine that you downvoted me, but also let's try to keep an open and inclusive culture? I know it's a beginner question. I'm not a beginner, I use APIs all the time and have designed them as well. Just how I used servers without knowing for 5 years the semantic meaning behind it [1]. Understanding things deeply in that way is not my forte. [1] Though most people still don't know that clients/servers are roles of computer programs. Many programmers conflate servers with actual hardware in the sense of "a computer can be a client of a server". Well, no a piece of code can be a client to another piece of code and a server can be a piece of code to another piece of code. They're roles, not distinct hardware. [2] Claude mentions: Analog World Interfaces Door handle - The interface to a door mechanism. Whether it's a simple latch or complex electronic lock, you just turn/push the handle. An interface is basically the part you touch/use without needing to understand what's behind it.
- mlhpdx 1y agoHaving built a bunch of low level network APIs I think the author hits on some good, common themes. Versioning, etc. matter (or don’t) for binary UDP APIs (aka protocols) just as much as for any web API.
- wener 1y agoI still try think /v1 /v2 is a break, I don't trust you will keep v1 forever, otherwise you'll never introduce this execuse. I'd like to introduce more fields or flags to control the behavior as params, not asking user to change the whole base url for single new API.
- calrain 1y agoI like this pattern. When an API commits to /v1 it doesn't mean it will deprecate /v1 when /v2 or /v3 come out, it just means we're committing to supporting older URI strategies and responses. /v2 and /v3 give you that flexibility to improve without affecting existing customers.
- swagasaurus-rex 1y agoCursor based pagination was mentioned. It has another useful feature: If items have been added between when a user loads the page and hits the next button, index based pagination will give you some already viewed items from the previous page. Cursor based pagination (using the ID of the last object on the previous page) will give you a new list of items that haven't been viewed. This is helpful for infinite scrolling. The downside to cursor based pagination is that it's hard to build a jump to page N button.
- echelon 1y agoYou should make your cursors opaque so as to never reveal the size of your database. You can do some other cool stuff if they're opaque - encode additional state within the cursor itself: search parameters, warm cache / routing topology, etc.
- rockwotj 1y agoCame here to say these same things exactly. Best write up I know on this subject: https://use-the-index-luke.com/sql/partial-results/fetch-next-page https://use-the-index-luke.com/sql/partial-results/fetch-nex...
- 0xbadcafebee 1y agoMost people who see "API" today only think "it's a web app I send a request to, and I pass some arguments and set some headers, then check some settings from the returned headers, then parse some returned data." But "API" means "Application Programming Interface". It was originally for application programs, which were... programs with user interfaces! It comes from the 1940's originally, and wasn't referred to for much else until 1990. APIs have existed for over 80 years. Books and papers have been published on the subject that are older than many of the people reading this text right now. What might've those older APIs been like? What were they working with? What was their purpose? How did those programmers solve their problems? How might that be relevant to you?
- spacechild1 1y agoYou are talking in past tense, but there are still many non-web APIs. Every software library has an API. I still find it incredibly annoying that the web folks have hijacked the term "API" as a short hand for "web API".
- stronglikedan 1y ago> the web folks have hijacked the term "API" as a short hand for "web API". I don't see it. API is too vague to mean one type of API, whether it's one from before the web, or a web API. As soon as there was more than one type of API, the term API became incomplete without a qualifier. Nothing was hijacked, and your sentence includes an incomplete term.
- spacechild1 1y agoWeb devs absolutely do use "API" as a synonym for "web API". I mean, the title of this very submission is "Everything I know about good API design". One could naively expect an article about API design in general, but it's only about web APIs.
- fanf2 1y ago> It comes from the 1940's originally Really?! That’s amazingly early. There were barely even subroutine libraries at that time. I’d love to see an example of "Application Programming Interface" from that time. (I don’t remember seeing the term until Microsoft started using it when talking about Windows in the 1990s; before then it was things like library functions or supervisor calls - but I didn’t have much experience at that point so I was probably missing some of the more collar-and-tie programmer lingo.)
- deleted 1y ago[deleted]
- achernik 1y ago> How should you store the key? I’ve seen people store it in some durable, resource-specific way (e.g. as a column on the comments table), but I don’t think that’s strictly necessary. The easiest way is to put them in Redis or some similar key/value store (with the idempotency key as the key). I'm not sure how would storing a key in Redis achieve idempotency in all failure cases. What's the algorithm? Imagine a server handling the request is doing a conditional write (like SET key 1 NX), and sees that the key is already stored. What then, skip creating a comment? Can't assume that the comment had been created before, since the process could have been killed in-between storing the key in Redis and actually creating the comment in the database. An attempt to store idempotency key needs to be atomically committed (and rolled back in case it's unsuccessful) together with the operation payload, i.e. it always has to be a resource-specific id. For all intents and purposes, the idempotency key is the ID of the operation (request) being executed, be it "comment creation" or "comment update".
- rockwotj 1y agoYes please don’t add another component to introduce idempotency, it will likely have weird abstraction leaking behavior or just be plain broken if you don’t understand delivery guarantees. Much better to support some kind of label or metadata with writes so a user can track progress on their end and store it alongside their existing data.
- spixy 1y agoAlgorithm is that the key is changed everytime after result 200 from API or page is refreshed or changed to another.
- canpan 1y ago> many of your users will not be professional engineers. They may be salespeople, product managers, students, hobbyists, and so on. This is not just true for authentication. If you work in a business setting, your APIs will be used by the most random set of users. They be able to google for how to call your api in python, but not be able to do things like converting UTC to their local time zone.
- barapa 1y agoThey suggest storing the idempotency key in redis. Seems like if possible, you should store them in whatever system you are writing to in a single transaction with the write mutations.
- tiffanyh 1y agoHere’s also some good recommendations: https://jcs.org/2023/07/12/api https://jcs.org/2023/07/12/api
- JimDabell 1y agoThat’s good too. Regarding: > Be descriptive in your error responses This is a useful standardised format: RFC 7807: Problem Details for HTTP APIs — https://datatracker.ietf.org/doc/html/rfc7807 https://datatracker.ietf.org/doc/html/rfc7807
- JimDabell 1y agoThis is great. One thing I would add: The quality of the API is inversely correlated to how difficult it is to obtain API documentation. If you are only going to get the API documentation after signing a contract, just assume it’s dismally bad.
- rubenvanwyk 1y agoThis. It usually also means no OpenAPI standards, which makes integration much more difficult.
- josevalerio 1y agoSometimes you get the docs emailed in a password protected spreadsheet :')
- mrkeen 1y ago> That way you can send as many retries as you like, as long as they’ve all got the same idempotency key - the operation will only be performed once. I worked in an org where idempotency meant: if it threw an exception this time, it needs to throw the same exception everytime.
- cjblomqvist 1y agoPragmatism rules here, but yeah - the common way to do this (at least if you have keys generatable by the client), eg. using REST, is to not allow POSTs, but only PUT. Most APIs I've seen use PUT solely for updates (of existing items), but as is obvious from the wording it's not the original intention.
- deterministic 1y agoIt’s rare to read an article where I agree 100% with everything written. Bravo!
- jillesvangurp 1y agoAPI versioning mostly just means things perpetually stuck at v1. You might have the intention to change things up, but you never will. Putting version numbers in a URL is a bit of a kludge. v1 is the most common version, by far, you will ever see in a url. v2 is rare. v3 is more common strangely. I don't think I've seen a v4 or v5 or higher in the wild very often. That's just not a thing. My theory is that v1 is the quick and dirty version that developers would like to forget exists. v2 is the "now we know what we're doing!" version and that's usually quickly followed by v3 because if you can change your mind once you can do it twice. After which people just tell developers to quit messing with the API already and keep things stable. v4 and v5 never happen. Another observation is that semantic versioning for API urls here seems rare. Reason: it's inconvenient for clients to have to update all their URLs every time some developer changes their mind. Most clients will hard code the version. Because it never changes. And because it is hard coded, changing the version becomes inconvenient. My attitude towards URL based versioning is that you could do it but it's not a tool that you get to use much. Therefore you can safely skip it and it won't be a problem. And in the worst case where you do need it, you can easily add a v2 URL space anyway. But you probably never will as you are unlikely to deprecated the entirety of your API. There are other ways to deal with deprecating APIs. You can just add new paths or path prefixes in your API as needed. You can use a different domain. Or you can just remove them after some grace period. It depends. Versioning is more aspirational than actually a thing with APIs. We do version our API but via client headers. Our API client sends a version header. And we check it server side and reject older versions with a version conflict response (409). This enables us to force users of our app to update to something we still support. The version number of our client library increments regularly. Anything falling behind too far we reject. This doesn't work for all use cases. But for a web app this is completely fine.
- TrueSlacker0 1y agoThere is always an outlier, but Quickbooks is currently on minor version 75.
- shrx 1y agoDiscord API [0] currently defaults to version 6, with version 10 being already available. [0] https://discord.com/developers/docs/reference https://discord.com/developers/docs/reference
- deathanatos 1y agoPagination: do not force me to drink from a paginated coffee stir. I do not want 640 B of data in a response, and then have to send another response for the next 640 B. And often, pagination means the calls are serialized, so I'm just doing nothing but waiting for round trip latency after round trip latency for the next meager 640 B of data. Azure I'm looking at you. Many of their services do this, but Blob storage is something else: I've literally gotten information-free responses there. (I.e., 0 B of actual data. I wish I could say 0 B were used to transfer it.) When you're designing, think about how big a record/object/item is, and return a reasonable number of them in a page. For programmatic consumers who want to walk the dataset, a 640 KiB response is really not that big, and I've seen so many times responses orders of magnitude less, because someone thought "100 items is a good page size, right?" and 100 items was like 4 KiB of data. > If you have thirty API endpoints, every new version you add introduces thirty new endpoints to maintain. You will rapidly end up with hundreds of APIs that all need testing, debugging, and customer support. You version the one thing that's changing. As much as I hate the /v2/... form of versioning, nobody reversions all the /v1/... APIs just because one API needed a /v2. /v2 is ghost town, save for the /v2 APIs.
- mulholio 1y agoIt’s certainly been my experience that page sizes should be bigger than you initially expect. Paginated endpoints are typically iterated all the way through meaning you’re going to return that data anyway. May as well save the additional overhead from multiple requests. Not implementing pagination at the outset can be problematic, however. If you later want to paginate data (e.g. if the size of your data grows) then it’s going to be a breaking change to implement that later. Big page sizes but with pagination can be a reasonable balance.
- atoav 1y agoYeah, pagination ia a great option — maybe even a good default. But don't make it the only choice, give developers the choice to make the tradeoff between number of requests and payload size.
- rirze 1y ago
- miki123211 1y ago> You should let people use your APIs with a long-lived API key This is an extremely unpopular opinion, but I would go even further. I think you should let people use your API with just an username and a password. It should by no means be the only way people can use your API. Put very low users-per-IP rate limits on that approach if you want to, to force lazy but professional software developers to go the oAuth route before their app gets to production. For one-off scripts though, APIs that let you do this are a breath of fresh air. If your API is based on API keys, you will be tempted to do things that really annoy new users of that API. People don't want to tell you what their app name is, they don't know that yet. They're certainly not picking a purpose they need this API for from a list of five, not if it doesn't include "completing a classroom assignment I don't really care about and want to finish as quickly as possible." They for sure don't yet know what scopes they might possibly need, even if to you, their names are descriptive and obvious. If you allow user-password authentication, you take away the ability to shoot yourself in the foot in this way.
- minzak 1y agoNice article. I'd also highly recommend "How To Design A Good API and Why it Matters" video from Joshua Bloch (co-author of Java). He digs much deeper, mostly at code level rather than JSON level but the same principles apply. Even though this video is almost 20 years old, the topics are as significant today as they were back then. https://www.youtube.com/watch?v=aAb7hSCtvGw https://www.youtube.com/watch?v=aAb7hSCtvGw
- weinzierl 1y ago"Think about it - if you send three DELETE comments/32 requests in a row, it won’t delete three comments. The first successful request will delete the comment with ID 32, and the remaining requests will 404 when they can’t find the already-deleted comment." Not necessarily. Many implementations return HTTP 204 for any DELETE that succeeds in the sense that the element is gone regardless if it had been there before. To me this always made much more sense than 404.
- BrainyZeiny 1y agoIn 2025, leaving GraphQL out of a discussion on modern API design is like writing about web frameworks and downplaying React. It may not be right for every use case.. but it has become foundational in many serious frontend/backend architectures, and that deserves acknowledgment. GraphQL isn’t just another protocol. It’s a paradigm shift in how we think about designing and consuming APIs. The author downplays its role, but in practice, GraphQL enables cleaner contracts between frontend and backend, encourages typed schemas, and dramatically reduces over-fetching and under-fetching. That’s not a minor point .. that’s central to what most developers care about when consuming APIs. Regarding caching: yes, REST has traditional browser and CDN-based caching, but GraphQL is absolutely cacheable too. Tools like Apollo Client and Relay have built-in normalized caches that are far more granular and powerful than most REST setups. At the infrastructure level, persisted queries and CDN layer solutions (like GraphCDN or Stellate) further optimize caching behavior. So the claim that “you can’t cache GraphQL” is outdated at best.
- nevertoolate 1y agoCaching is straw-man. Complexity tends to be higher to implement a graphql backend than for e.g. type-spec => openapi backend. For the simple case the simpler solution wins imo. For the complex case it can be a toss-up, but it seems that performance and security can be a big deal-breaker for graphql, so maybe only big enterprises can afford to go down that route. I'm not sure what you mean by the react analogy, react seems to be far more popular than graphql in their respective areas.
- VGHN7XDuOXPAzol 1y agoGraphQL has some impressive points, but sometimes feels like it shifts too much control to the client. I'm on the fence about it. There are performance footguns (like recursion, for which you'd have to consult your GraphQL server library for mitigations). There is often a built-in 'introspection' endpoint, which many consider a security faux-pas (to which I disagree — I think it's pretty noble, like having built-in OpenAPI docs) BUT you can easily craft a recursive query using just this endpoint that will take (some) GraphQL servers down. There are plenty of posts written on the matter and I'm sure there are mitigations, but my first exposure to GraphQL was on someone else's project (a respectable engineer who I consider very skilled) and within the first day I had noticed this intriguing structural hazard and taken the server down... It therefore seems to be a tool that is possibly difficult to 'hold correctly'; at least people should be cautious about going in without doing their research about these things. Probably a maturity issue, but one that people ought to be aware of? Other gripes: It's displeasing how the HTTP status code does not correlate with the actual success response of the API, which makes typical request logging less useful. I guess it also makes it harder to provide optimised hot paths on the server (because your client team might shift their queries around, or whatever). In previous experience I also find that having easily-recognisable names for API endpoints (like `GET /repositories`) makes talking about them, and recognising them, easier than the more-opaque-feeling GraphQL approach.
- randallsquared 1y agoI don't really understand why you'd bring up DELETE in a passage about idempotence and not PUT.
- curtisszmania 1y ago[dead]
- Joker_vD 1y ago> Instead of using OFFSET, the query becomes WHERE id > cursor ORDER BY id LIMIT 10 Wait. Surely "ORDER BY id OFFSET 20 LIMIT 10" works about the same as "WHERE id > cursor ORDER BY id LIMIT 10", if "id" is indexed?
- asddubs 1y agono, because it has to count the amount of matching rows preceding the offset rows to determine the offset, i.e. iterate over all preceding rows. The cursor provides a starting point for the offset so in this instance it's not necessary. https://use-the-index-luke.com/sql/partial-results/fetch-next-page https://use-the-index-luke.com/sql/partial-results/fetch-nex...
- Joker_vD 1y agoIt only has to count if the index doesn't store the amounts of records in the "chunks" it manages, does it? I'm pretty sure B-trees do actually store the sizes of the subtrees.
- VGHN7XDuOXPAzol 1y agoAfaik Postgres doesn't. In my exposure it'd be quite uncommon for a b-tree to store the size of a subtree; would cause more churn/writes when updating trees. Perhaps some of the page-level Copy-on-Write databases (LMDB?) might do this, since they have to rewrite ancestor pages anyway.
- sushrut1058 1y agoGreat article!
- dev_l1x_be 1y agoSean Goedecke's blog posts become my foundation folder for prompting LLMs to design new systems. He captures so much with few blog posts, incredible.
- hackrmn 1y agoI've always been a staunch opponent of using `/v1/` kind of element in the URL. I understand its function and the convenience it allows for "versioning", but I grew up with HTTP and I always liked how it insisted the URL is well, the _location_ of the _resource_, and `/v1/` just muddies things up being in the URL -- it's obviously not a version of the resource that `/v1/` would be indicating, but of the API implementation, which is the first telltale sign that it's an architectural "blunder", and these compound in my experience, always and invariably given enough time. If the consumer wants to consume a specific version of the API, the means to do so can be implemented with an alternative domain name, or -- even better (who wants to maintain alternative domain names) -- with a request _header_, e.g. `X-API-Version: v1` (or another one, perhaps a standardised one). In any case, the `/v1/` thing is something of cargo cult programming -- I remember someone proposed it a good while ago, and it's been adopted since without much afterthought, it seems. It doesn't make sense to debate pros and cons of REST/HATEOAS if your resource identifier scheme is poorly designed, IMO.