What are Appwrite's new custom IDs ?
Tags: javascript, opensource, discuss, programming
Published: 2022-01-10 09:28:22

At Appwrite, we strive to make software development for fellow Appwriters not only easy but also fun and beautiful. We want the experience of using Appwrite to be as pleasant as possible. Introducing custom ID support was another step towards that. So what are custom IDs?

![Create project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9l1hapzde9l3i9s57oxp.png)
 

## 👋 Overview

[Appwrite](https://appwrite.io/) is open source backend-as-a-service that abstracts all the complexity involved in building a modern application by providing you with a set of **REST and realtime APIs** for your core backend needs. Appwrite handles user authentication and authorization, databases, file storage, cloud functions, webhooks and much more! If there is anything missing, you can extend Appwrite using your favourite backend language.

Appwrite has various resources like documents, collections, files, users, teams, functions, and more, all identified by ( you guessed it) IDs! Until now, these IDs were automatically generated. While it made a lot of sense for them to behave this way, it presented some difficulty for developers migrating from a development to a production environment having to manipulate their IDs. Custom IDs give control back to developers allowing them to either use their own or choose auto-generated ones. Developers using Appwrite will now be able to assign a meaningful ID to their collections, functions, and more.

Custom ID support was one of the highly requested features by our community and was only possible with the recent [Appwrite v0.12](https://dev.to/appwrite/its-here-announcing-the-release-of-appwrite-012-5c8b). Acting upon the feedback from our incredible community, with the new Appwrite version, we've introduced support for custom IDs for various resources provided by Appwrite. Now let's dive into how we have implemented custom IDs and how we still support the previous auto-generated IDs.

## 🔎 Custom ID Implementation

Previously, all of the `create` endpoints in Appwrite automatically generated 13 character long unique IDs for new resources. However, with support for custom IDs, we also wanted to allow developers to easily choose an auto-generated ID, if they wanted to. We added a new `resource ID` parameter to all create endpoints of the resources that accept custom IDs. The ID can be at most 36 characters in length. It can be any valid alphanumeric value containing underscore, period, or hyphen, however, it cannot start with a special char. Finally, to allow developers to choose auto-generated IDs, we added a `unique()` keyword, upon passing which, Appwrite will automatically generate the ID like before.

We have also made one tiny modification to auto-generated IDs. Previously there was a slight chance of ID duplication if they were created within the same microsecond and on the same host. We decided to prefix the auto-generated IDs with a 7-char random string to give them more entropy and prevent duplication. The new auto-generated IDs are now 20 characters in length with this version. We now understand how custom IDs are implemented and validated, next let's look at which resources in Appwrite support custom IDs.

## 🤔 Do all resources support custom IDs?

Appwrite has many resources but not all of them support the new custom ID API. We had a lot of debates on which resources need to support custom IDs and we concluded that it only made sense to support custom IDs on resources that the developer would interact with directly. These include

- Project
- User
- Collection
- Document
- Function
- File
- Team

## 🤨 How would it help me? 

The first and foremost benefit of having custom ID support is allowing developers to assign meaningful IDs to resources. For example, to create a collection of books we can now give it an id of `books` and access the documents in the collection using the assigned ID. With this, adding new books to the collection using the API looks more elegant, and as a developer, you will not have to keep track of a random string to refer to your `books` collection.

Let's see how the code for listing documents look before and after the custom ID support.

- **Listing documents in web before custom ID support**

```js
const sdk = new Appwrite();

sdk
    .setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
    .setProject('5df5acd0d48c2') // Your project ID
;

let promise = sdk.database.listDocuments('5df5acd0d48c2');

promise.then(function (response) {
    console.log(response); // Success
}, function (error) {
    console.log(error); // Failure
});
```
* **Listing documents in web with custom ID support**

```js
const sdk = new Appwrite();

sdk
    .setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
    .setProject('my-project') // Your project ID
;

let promise = sdk.database.listDocuments('books');

promise.then(function (response) {
    console.log(response); // Success
}, function (error) {
    console.log(error); // Failure
});
```
The code is much more readable with custom IDs. We know exactly which project and collection we are trying to access.

Secondly, if you were to setup two different Appwrite projects for your development and production environments, you had to keep track of the project IDs, collection IDs, function IDs and more in order to access those resources. You would need to create a separate config based on mode - development or production. Although it's not too difficult to create different configs per environment, with custom IDs that's one less thing to worry about. The project ID, collection ID and function ID can all be the same across development and production environments. Only the endpoints may be different.

Last but not least, while using REST API directly to access resources, endpoints look more elegant. For example, we are trying to get a list of documents for a Books collection that we have created. Previously with auto-generated ID, the endpoint would look like the following.

```
https://localhost/v1/database/collections/eead3asadf3e1/documents
```
By looking at the endpoint, it's not clear which collection we are trying to access and what documents might be. The same endpoint with custom IDs set for collection as `books` will look like the following.

```
https://localhost/v1/database/collections/books/documents
```

Anyone looking at the URL can now easily understand that we are trying to access documents of the `books` collection. These are the benefits of having custom ID support. It will make working with Appwrite much more straightforward and elegant. Next, we will look at the breaking changes we introduced to support custom IDs.

## ✏️ Creating Resources after custom ID Support

All the creation endpoint of the resources that support custom ID now has a new required parameter `resourceId`. For example, endpoint to create file, requires `fileId` , and the method to create file in Storage service on all SDKs now requires `fileId`. These parameters can be a custom IDs or a `unique()` keyword if we want ID to be auto-generated like before. Keep in mind that the `id` parameter is required.

### Example: Creating a Collection

Creating a collection now requires an additional `collectionId` parameter. For example, the new call to create a collection would look like the following.

**NodeJS SDK**

```js
const sdk = require('node-appwrite');

// initialize client

let database = new sdk.Database(client);

database.createCollection('authors', 'Authors', 'collection', ['role:all'], ['role:member']).then(function(response) {
  console.log(response);
}, function(error) {
  console.error(error);
});
```
**Dart SDK**

```dart
import 'package:dart_appwrite/dart_appwrite.dart';

void main() async {
  // initialize client

  final database = Database(client);
  try {
    final collection = await database.createCollection(
      collectionId: 'authors',
      permission: 'collection',
      name: 'Authors',
      read: ['role:all'],
      write: ['role:member']
    );
    print(collection.toMap());
  } on AppwriteException catch(e) {
    print(e.message);
  }
}
```

This will create an Authors collection with `authors` as the collection ID with `collection` level read and write permission, `role:all` and `role:member` respectively. Learn more about this and other functions of database service by visiting our [docs](https://appwrite.io/docs/database#permissions).

If you instead want to auto generate the ID for the collection, you can simply change the `database.createCollection` to the following.

**NodeJS SDK**

```js
database.createCollection('unique()', 'Authors', 'collection', ['role:all'], ['role:member']).then(function(response) {
  console.log(response);
}, function(error) {
  console.error(error);
});
```
**Dart SDK**

```dart
  final collection = await database.createCollection(
    collectionId: 'unique()',
    name: 'Authors',
    permission: 'collection',
    read: ['role:all'],
    write: ['role:member']
  );
```
## 🤔 Backward Compatibility

In order to keep things smoother for everyone, we try to keep breaking changes to the minimum. However, sometimes breaking changes are necessary. Even then, we try to make it backward compatible to smoother migration as much as possible. With the introduction to custom ID support, we have also introduced request filters to make it backward compatible. With request filters, we capture every request before reaching the endpoint handler and automatically add the default `unique()` value to id parameters to support automatic generation like before. For example, when you make a request to create a user from an old SDK, our request filter will see that the request is missing the `userId` parameter and adds `userId=unique()` and forwards the request to the create user endpoint. This way, the handler gets all the required parameters and works as intended. You need to add the `x-appwrite-response-format` header to the request to enable this logic. This is done automatically by SDKs.

## 🙏 Conclusion

Custom IDs can be a very beneficial feature when used wisely. It will make accessing APIs more elegant and understandable. It allows us to give meaningful names to various resources and access them easily from your client applications. If you'd like to learn more about Appwrite you can visit the [official docs](https://appwrite.io/docs). You can also check out our latest release in the [release announcement](https://dev.to/appwrite/its-here-announcing-the-release-of-appwrite-012-5c8b). If you're stuck or need help with Appwrite, you can always join our [Discord community](https://appwrite.io/discord) of awesome Appwriters.

## 📚 Learn more

You can use following resources to learn more and get help regarding Appwrite and it's services

- 🚀 [Appwrite Github](https://github.com/appwrite)
- 📜 [Appwrite Docs](https://appwrite.io/docs)
- 💬 [Discord Community](https://appwrite.io/discord)