Skip to content

Commit 57de9c6

Browse files
Merge pull request #2699 from appwrite/new-string-types
2 parents 280df95 + 7b166f6 commit 57de9c6

File tree

27 files changed

+362
-102
lines changed

27 files changed

+362
-102
lines changed

.optimize-cache.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@
684684
"images/blog/new-roles/console.png": "177070ba0a364ff0a6e1f78874adaf66f58e2b6faf662a5cd42e8142829eb224",
685685
"images/blog/new-roles/console2.png": "101f592e5776f64e0d5f5273631879412103efaa4f1943b58d689893a2f08b45",
686686
"images/blog/new-roles/cover.png": "d1148cc754a43599dd7b28760389d0fa2f366b912f3f9c31f237b96b87036900",
687+
"images/blog/new-string-types/cover.png": "431debf3c5b326220ebed21b835f6e3d8f38b7cfc2b71f320cbca5773e524b40",
687688
"images/blog/new-website.png": "14b68b0d3b3bdb953a2b2c59af5f041b8bdab28f68a1757895cc2ec0a4b6a011",
688689
"images/blog/nextjs-output-modes/cover.png": "d4eeb4585955564b37c9e65e3b9be50e2109e4c9f546dbe207c27b55838d7e06",
689690
"images/blog/nextjs-standalone-builds/cover.png": "873360c0097ee41bac5fb3fdcab5329f73ca991a53b15e03dc6ed22449cf247e",
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
layout: post
3+
title: "Introducing new string column types for Appwrite Databases"
4+
description: Appwrite Databases now supports varchar, text, mediumtext, and longtext column types, giving you explicit control over how string data is stored and indexed. The legacy string type is now deprecated.
5+
date: 2026-02-12
6+
cover: /images/blog/new-string-types/cover.png
7+
timeToRead: 5
8+
author: eldad-fux
9+
category: announcement
10+
featured: false
11+
---
12+
13+
Until now, Appwrite offered a single `string` column type that abstracted away four different storage types, based on the size you specified. This meant you had no visibility into how your data was actually stored, how it could be indexed, or why certain size limits existed.
14+
15+
Today, we're introducing four explicit string column types: `varchar`, `text`, `mediumtext`, and `longtext`.
16+
17+
# The new string types
18+
19+
Each type has a clear purpose and a defined maximum size:
20+
21+
| Type | Max characters | Indexing |
22+
|--------------|-------------------|-----------------------------------------------|
23+
| `varchar` | 16,383 | Fully indexable if size < 768 |
24+
| `text` | 16,383 | Prefix indexing only |
25+
| `mediumtext` | 4,194,303 | Prefix indexing only |
26+
| `longtext` | 1,073,741,823 | Prefix indexing only |
27+
28+
## Varchar vs Text
29+
30+
Both `varchar` and `text` share the same maximum size, but they behave differently under the hood.
31+
32+
`varchar` is stored inline in the table row and counts towards the 64KB maximum row size shared across all columns. If the size is less than 768 characters, the column can be fully indexed, making it ideal for short strings you need to query, sort, or filter on, like names, slugs, or identifiers.
33+
34+
`text` is stored off-page, with only a 20-byte pointer kept in the table row. This means it doesn't eat into your row size budget, but it can only be indexed with prefix or functional indexes. Use `text` when you need string storage without full indexing, like descriptions or notes.
35+
36+
## Mediumtext and Longtext
37+
38+
For larger content, `mediumtext` supports up to ~4 million characters and `longtext` up to ~1 billion characters. Both are stored off-page and support prefix indexing only. These are the right choice for storing things like article bodies, logs, or serialized data.
39+
40+
# Why we made this change
41+
42+
When we originally designed the `string` type, the intent was to simplify things. One type, one API, and Appwrite would handle the storage details for you. But over time, through community feedback and our own experience, we realized that this abstraction compromised on important details like visibility and control. Finding the right balance between simplicity and transparency is a difficult task, and we believe responding to user feedback and experience is what makes a product better.
43+
44+
The issue was that the `string` type hid storage behavior that developers needed to see in order to make informed decisions about their data structures. This led to problems for both human engineers and AI agents alike.
45+
46+
- **Hidden storage behavior.** The `string` type required you to specify a size, but gave no indication of how that size mapped to actual storage. There was no way to know that `size: 10000` would produce a `VARCHAR(10000)` stored inline, while `size: 20000` would quietly switch to a `TEXT` column stored off-page. Developers were making sizing decisions without seeing the consequences.
47+
- **Invisible row width limits.** Appwrite uses MariaDB under the hood, which has a fixed 64KB maximum row width. Varchar columns are stored inline and count towards that limit. A developer creating a `string` column with `size: 10000` (a Varchar internally) for something like blog content would unknowingly consume a large chunk of the row budget, limiting how many other columns the table could have.
48+
- **Difficult for AI agents to reason about.** When AI agents provision database schemas, they need clear type semantics to make good decisions. The `string` type gave them nothing to work with, no signal about storage trade-offs, no way to differentiate between a short identifier and a long-form text field.
49+
50+
We saw both sides of this problem firsthand while building [Imagine](https://imagine.dev), our AI-powered builder for web apps, which uses Appwrite under the hood for out-of-the-box server functionality. Imagine runs an Appwrite Cloud agent that provisions database resources on your behalf using the Appwrite CLI and `appwrite.json` as the schema. The agent is trained to build sophisticated architectures, and it would easily create just enough string columns to hit the row width limit.
51+
52+
We could have fixed this with better prompting for Imagine, but that would only solve it for one tool. Instead, we made the types themselves more explicit, so the right choice is obvious whether you're writing code by hand, using the Console, or letting an AI agent provision your schema. With the new types, both developers and agents can now see exactly what they're working with and make better decisions around their data structures.
53+
54+
# Using the new types
55+
56+
Here's how to create a table with the new types using the Node.js SDK:
57+
58+
```server-nodejs
59+
const sdk = require('node-appwrite');
60+
61+
const client = new sdk.Client()
62+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
63+
.setProject('<PROJECT_ID>')
64+
.setKey('<API_KEY>');
65+
66+
const tablesDB = new sdk.TablesDB(client);
67+
68+
await tablesDB.createTable({
69+
databaseId: '<DATABASE_ID>',
70+
tableId: '<TABLE_ID>',
71+
name: 'articles',
72+
columns: [
73+
{
74+
key: 'title',
75+
type: 'varchar',
76+
size: 255,
77+
required: true
78+
},
79+
{
80+
key: 'summary',
81+
type: 'text',
82+
required: false
83+
},
84+
{
85+
key: 'body',
86+
type: 'mediumtext',
87+
required: false
88+
},
89+
{
90+
key: 'raw_data',
91+
type: 'longtext',
92+
required: false
93+
}
94+
]
95+
});
96+
```
97+
98+
# Deprecation of the string type
99+
100+
The `string` column type is now deprecated, but we will continue to maintain full backward support for it. Existing `string` columns will keep working as they do today, and we recommend using the explicit types for all new columns going forward.
101+
102+
Previously, `string` would internally pick between `varchar`, `text`, `mediumtext`, and `longtext` based on the size you specified, without giving you any indication of which one was being used. The new types remove that ambiguity entirely.
103+
104+
# Available now
105+
106+
These changes are live on Appwrite Cloud. You can start using the new column types today through the Console, SDKs, and CLI.
107+
108+
# More resources
109+
110+
- [Read the Tables documentation](/docs/products/databases/tables)
111+
- [Announcing Transactions API: Reliable multi-record writes across tables](/blog/post/announcing-transactions-api)

src/routes/docs/advanced/security/encryption/+page.markdoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ You can enable encryption by going to your bucket's **Settings** > **Security se
1515
Files are encrypted with AES-128 in Galois/Counter Mode (GCM).
1616

1717
## Databases {% #databases %}
18-
Database columns support encryption for string columns. This feature is available on Pro plans and higher. When creating a string column in the UI, encryption can be enabled using a toggle option.
18+
Database columns support encryption for text columns (varchar, text, mediumtext, and longtext). This feature is available on Pro plans and higher. When creating a text column in the UI, encryption can be enabled using a toggle option.
1919
Columns are encrypted with AES-128 in Galois/Counter Mode (GCM).
2020

2121
{% info title="Querying encrypted columns" %}

src/routes/docs/products/databases/csv-imports/+page.markdoc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ x0v4p8ncq2,To Kill a Mockingbird,Harper Lee,1960,false
3737

3838
Different column types handle empty values differently:
3939

40-
- **String columns:** Empty values are interpreted as empty strings. To add null values to a string column, use the value `null` without quotes.
40+
- **Text columns (varchar, text, mediumtext, longtext):** Empty values are interpreted as empty strings. To add null values to a text column, use the value `null` without quotes.
4141
- **Integer columns:** Empty values are interpreted as `null`.
4242
- **Boolean columns:** Empty values are interpreted as `null`.
4343
- **Array of any type:** Empty values are interpreted as empty arrays.
@@ -115,12 +115,13 @@ If your CSV file contains characters like double quotes (`"`) or commas (`,`), y
115115

116116
There are different ways to escape commas based on different scenarios.
117117

118-
- If your column type is a **string**, you can enclose the value in double quotes (`"comma,used,here"`).
119-
- If your column type is a **string array**, you need to escape double quotes within the array to use a comma (`"one,two,""comma,allowed,here"""`).
118+
- If your column type is a **text type** (varchar, text, mediumtext, or longtext), you can enclose the value in double quotes (`"comma,used,here"`).
119+
- If your column type is a **text type array** (varchar, text, mediumtext, or longtext), you need to escape double quotes within the array to use a comma (`"one,two,""comma,allowed,here"""`).
120+
120121

121122
## Double quotes
122123

123-
If you want to add double quotes to a string column, you need to escape them by doubling them (`""`), otherwise it will be treated as an array.
124+
If you want to add double quotes to a text column (varchar, text, mediumtext, or longtext), you need to escape them by doubling them (`""`), otherwise it will be treated as an array.
124125

125126
# Import rows from the Console {% #import-console %}
126127

src/routes/docs/products/databases/legacy/type-generation/+page.markdoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ Suppose you want to generate types for a collection with data on books with the
5555
"attributes": [
5656
{
5757
"key": "name",
58-
"type": "string",
58+
"type": "varchar",
5959
"required": true,
6060
"array": false,
6161
"size": 255,
6262
"default": null
6363
},
6464
{
6565
"key": "author",
66-
"type": "string",
66+
"type": "varchar",
6767
"required": true,
6868
"array": false,
6969
"size": 255,
@@ -79,7 +79,7 @@ Suppose you want to generate types for a collection with data on books with the
7979
},
8080
{
8181
"key": "category",
82-
"type": "string",
82+
"type": "varchar",
8383
"required": false,
8484
"array": false,
8585
"elements": [
@@ -91,7 +91,7 @@ Suppose you want to generate types for a collection with data on books with the
9191
},
9292
{
9393
"key": "genre",
94-
"type": "string",
94+
"type": "varchar",
9595
"required": false,
9696
"array": true,
9797
"size": 100,

0 commit comments

Comments
 (0)