Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

pascual's avatar

Some thoughts on REST naming conventions for singletons

Hello everyone, I have been pondering on some general thoughts regarding the topic of REST naming conventions when dealing with singletons.

It seems to be that most of the advice and best practices on the subject is from the viewpoint of an enduser with an extensive access to the final application. Let me try to explain what I mean. I might be overlooking something very fundamental here, so I would be extremely grateful if anyone would share their thoughts with me.

A typical "happy path" example

In the domain of "users", users would be a collection of users and a user would be a singleton representing a specific user.

Typically, if following the usual conventions, the routing for accessing these would be something like this:

// Get a collection of some or all users.
Route::get('/users', [UsersController::class, 'index']);

// Get a single user using a unique identifier explicitly.
Route::get('/users/{id}',  [UsersController::class, 'show']);

// Get a single user using route model binding.
Route::get('/users/{user}',  [UsersController::class, 'show']);

The above example will is an example of how that convention would be used, and can be applied to countless use cases. The Laracasts video on this in the Laravel from scratch course elaborates on this.

The problem

However, to me there is a problem with this convention and I can't seem to figure out a way to address it without straying away from said conventions.

When put in the context of someone using the application I see a problem when differentiating between different types of end users. A user the should be able to handle both a collection and a singleton is easy to write RESTful solutions for, just see above. But for the user that should only be able to access a singleton I see a problem.

To the user with the user id 69, the url /users/69 doesn't really make sense if said user should never be able to access any other user singletons. Having a route for /users/{id} implies that there could be several available, and incrementing or decrementing the value could might yield access. This implication only makes sense for someone give the permission to access several singletons, to anyone else it is never an option. And if the url should convey semantic information, the convention discussed here makes for bad practise when dealing with the case when an enduser is to access his only available singleton.

Sure, you can't protect the routes, but in my opinion this is a lesser solution when we are striving for stringent conventions as to naming.

That user might access his singleton by accessing /home/profile for instance, and using the convention the only way to represent state then would be to access that information without the url, for instance using session values.

How are you handling this in a coherent and consistent manner in your routes, dear people?

0 likes
5 replies
martinbean's avatar

@pascual I’m struggle to actually deduce the crux of your question from your extensive write-up. RESTful APIs tend to work around the concept of resources. If there’s a “user” resource, then you can work with a collection of users, or a single user resource.

To the user with the user id 69, the url /users/69 doesn't really make sense if said user should never be able to access any other user singletons. Having a route for /users/{id} implies that there could be several available, and incrementing or decrementing the value could might yield access.

Yes. And this is one of the reasons you should not use auto-incrementing primary keys in your URLs. Use an alternative, unguessable identifier such as UUIDs or hashids. A user shouldn’t be able to scrape your database by writing a script that simply executes API requests and increments the ID by one. Businesses have been killed due to that.

That user might access his singleton by accessing /home/profile for instance, and using the convention the only way to represent state then would be to access that information without the url, for instance using session values.

RESTful APIs are typically stateless, so you shouldn’t be using sessions. If you want a user to be able to access their information without knowing their ID, then you could take Facebook’s lead and have an endpoint with a URI like /me.

Also, I don’t know why you keep saying “singletons”. Singleton is a design pattern; not a term for a single resource in a REST API.

pascual's avatar

Sorry for not replying, I have not received or seen any notifications from this thread.

Thank you for your detailed input, @martinbean

As to my use of the term singleton, let me try to explain myself a bit better than in my previous post. I am aware of the single design pattern, but that was not what I was referring to. I was referring to the mathematical concept of a singleton (sometimes also called a unit set).

Within category theory this is very useful as the mathematical definition of a singleton is a set with the cardinality (number of elements) of only one, and always only one. And the topic I tried to think aloud about in my original post was the category theory that is REST.

Still using mathematical terms a set would be a collection of elements where the elements are distinguishable from each other. Using the REST approach, say we have a route called /blog-posts. A GET request to this route could return a set of all blog posts.

We could represent this using this notation (where B is blog posts and i is its unique ID):

B = {i, ...}

This set notation tells us that a any set of blog posts consists of 1 or infinity number for distinct blog posts. For the purpose of simplicity I had left out the possibility of the state where there are zero posts, which could perfectly well be the case at any given time of course.

This approach is extremely well suited for REST and working with the target's representational state.

A call to /blog-posts/99 also makes perfect sense because we know that it is a reference to a single, distinct item in the set.

However, the thing that gives of a bit a smell to me is when REST is used to refer to a singleton (as in a mathematical singleton).

The definition of a set that is a singleton is if, and only if, it has the cardinality of one. In a software application I can think of several cases where they would appear, especially if we factor in that the routes an end-user and an admin might have very different levels of utility value respectively. The route /users yielding a list of all users could be very useful for an administrator, but might not even be accessible to the end-user. In these cases the cardinality will always be one, ergo they will always be singletons.

Then what is it I am going on about then? Most best practices on how to apply REST to your API tells you to use a plural form for the resource name. See for instance REST API Naming Conventions and Best Practices Well, then let's examine the example of the concept of a user profile. To an admin it could make sense to view the metadata that makes up a single user profile, and that might be achieved with the route /users/1 to get the data for the user with the distinct ID of 1. Same as for the blog posts example above the distinct value 1 would refer to a distinct user within the users set:

USERS = {1, ...}

The route for the end user to access his profile (the meta data that is the profile) could for simplicity be named /profile, but this would be impossible to achieve statelessly. There is no way of distinguishing between different user profiles solely based on the URI.

We could use the route /users/1 or even /users/profiles/1

But to the end user the concept of a set collection of more than one user profile does not make sense. The user is by itself a single distinct item and has a 1-to-1 relationship with the profile. For user 1 to increment URI /user/1 to user/2 would only make sense if the user was trying to illegally access another user's profile.

The notation of the singleton concept of a user profile could be: P = {n+1} using the set theoretic definition of natural numbers. A user profile will therefore always have the cardinality of one.

Just as /users in admin land makes sense and can be represented as U = {0, ...} , /users in end user land would probably be an illegal route endpoint. But this logic seem to be tossed overboard when a single item from the set collection is to be returned. The admin accesses a single user by using the route /users/1 and so also does the end user and framework logic would prevent the user from accessing other user's profiles.

And this is what grinds my gears. The resources in REST are not supposed to be mapped to an entity but a set of entities. The resource invoices could have the URI /invoices and would map to a set collection of 0,1 or an infinite number of invoices. This logic breaks when the set collection is a singleton because it does not make sense to refer to a singleton by a distinct identity because there is only one of it. Using an id implies that it is not in fact a singleton.

Does it really matter?

Seeing that designing routes in a web application is based on very loose rules, it probably does not matter at all. But one of the objectives behind designing RESTful API's is to improve overall quality by being consistent. To me, just ignoring a logical flaw and hack around it is far from trying to be consistent. It at least gives off a smell that should be considered doing something about.

Huge disclaimer

I am in absolutely no way a mathematician nor a computer scientist, so I might very well have these concepts and ideas wrong. Feel free to correct me if needed.

martinbean's avatar
Level 80

@pascual What is it you’re actually asking? I don’t even know if you are asking a question because twice you’ve posted now, and especially the last post, just feels like reading a passage from a math textbook.

1 like
pascual's avatar

It was me thinking out loud and wondering if anyone else had any thoughts on naming conventions for singleton sets in REST.

Thanks for trying though. I think I will REST my case until I am able to describe it coherently. 😆

Cheers

pascual's avatar

I seem to have caused confusion when trying to put words to some thoughts I about the concepts of singletons within the scope of CRUD/REST and basic Laravel conventions a while back.

Now it however seems that someone way smarter than me, namely Laravel core developer Jess Archer, not only described but also built it and got it merged into Laravel.

https://laravel.com/docs/9.x/controllers#singleton-resource-controllers

Judging from the debate on Twitter this concept is still somewhat alien to some, but I must say I love this implementation and its proposed practical use.

https://twitter.com/taylorotwell/status/1597618943438786561?s=46&t=3iJ3V59l83akooAvmzrwqg

Please or to participate in this conversation.