---
layout: article
title: Atomic numeric operations
description: Safely increment and decrement numeric fields without race conditions. Perfect for counters, quotas, inventory, and usage metrics in high-concurrency applications.
---

Atomic numeric operations allow you to safely increase or decrease numeric fields without fetching the full row. This eliminates race conditions and reduces bandwidth usage when updating any numeric values that need to be modified atomically, such as counters, scores, balances, and other fast-moving numeric data.

These operations work with `integer`, `bigint`, and `float` columns. Use `bigint` columns when your counters or accumulators may exceed the 32-bit integer range.

# How atomic operations work {% #how-atomic-operations-work %}

Instead of the traditional read-modify-write pattern, atomic numeric operations use dedicated methods to modify values directly on the server. The server applies the change atomically under concurrency control and returns the new value.

**Traditional approach:**
1. Fetch row → `{ likes: 42 }`
2. Update client-side → `likes: 43`
3. Write back → `{ likes: 43 }`

**Atomic approach:**
1. Call `incrementRowColumn()` with the column name and the value to increment by
2. Server applies atomically → `likes: 43`

# When to use atomic operations {% #when-to-use-atomic-operations %}

Atomic numeric operations work well for:

- **Social features**: Likes, follows, comment counts
- **Usage metering**: API credits, storage quotas, request limits
- **Game state**: Scores, lives, currency, experience points
- **E-commerce**: Stock counts, inventory levels
- **Workflow tracking**: Retry counts, progress indicators
- **Rate limiting**: Request counters, usage tracking

# Perform atomic operations {% #perform-atomic-operations %}

Use the `incrementRowColumn` and `decrementRowColumn` methods to perform atomic numeric operations. The server will apply these changes atomically under concurrency control.

## Increment a field {% #increment-field %}

{% multicode %}
```client-web
import { Client, TablesDB } from "appwrite";

const client = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('<YOUR_PROJECT_ID>'); // Your project ID

const tablesDB = new TablesDB(client);

const result = await tablesDB.incrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'likes', // column
    value: 1 // value
});
```
```client-flutter
import 'package:appwrite/appwrite.dart';

final client = Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('<PROJECT_ID>');

final tablesDB = TablesDB(client);

final row = await tablesDB.incrementRowColumn(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'likes',
    value: 1
);
```
```client-apple
import Appwrite
import AppwriteModels

let client = Client()
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

let tablesDB = TablesDB(client)

let row = try await tablesDB.incrementRowColumn(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    column: "likes",
    value: 1
)
```
```client-android-kotlin
import io.appwrite.Client
import io.appwrite.services.TablesDB

val client = Client(applicationContext)
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

val tablesDB = TablesDB(client)

val row = tablesDB.incrementRowColumn(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    column = "likes",
    value = 1
)
```
```server-nodejs
const sdk = require('node-appwrite');

const client = new sdk.Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('<PROJECT_ID>') // Your project ID
    .setKey('<API_KEY>'); // Your secret API key

const tablesDB = new sdk.TablesDB(client);

const result = await tablesDB.incrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'likes', // column
    value: 1 // value
});
```
```server-python
from appwrite.client import Client
from appwrite.services.tables_db import TablesDB

client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<PROJECT_ID>') # Your project ID
client.set_key('<API_KEY>') # Your secret API key

tablesDB = TablesDB(client)

result = tablesDB.increment_row_column(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    column = 'likes', # column
    value = 1 # value
)
```
```rust
use appwrite::Client;
use appwrite::services::tables_db::TablesDB;

let client = Client::new()
    .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
    .set_project("<PROJECT_ID>")
    .set_key("<API_KEY>");

let tables_db = TablesDB::new(&client);

let result = tables_db.increment_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "likes",       // column
    Some(1.0),     // value
    None,          // max
    None,          // transaction_id
).await?;
```
```graphql
mutation {
    databasesIncrementRowColumn(
        databaseId: "<DATABASE_ID>",
        tableId: "<TABLE_ID>",
        rowId: "<ROW_ID>",
        column: "likes",
        value: 1
    ) {
        _id
        _tableId
        _databaseId
        _createdAt
        _updatedAt
        _permissions
        data
    }
}
```
{% /multicode %}

## Decrement a field {% #decrement-field %}

Use the `decrementRowColumn` method to decrease numeric fields:

{% multicode %}
```client-web
import { Client, TablesDB } from "appwrite";

const client = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('<YOUR_PROJECT_ID>'); // Your project ID

const tablesDB = new TablesDB(client);

const result = await tablesDB.decrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 5 // value
});
```
```client-flutter
import 'package:appwrite/appwrite.dart';

final client = Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('<PROJECT_ID>');

final tablesDB = TablesDB(client);

final row = await tablesDB.decrementRowColumn(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits',
    value: 5
);
```
```client-apple
import Appwrite
import AppwriteModels

let client = Client()
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

let tablesDB = TablesDB(client)

let row = try await tablesDB.decrementRowColumn(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    column: "credits",
    value: 5
)
```
```client-android-kotlin
import io.appwrite.Client
import io.appwrite.services.TablesDB

val client = Client(applicationContext)
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

val tablesDB = TablesDB(client)

val row = tablesDB.decrementRowColumn(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    column = "credits",
    value = 5
)
```
```server-nodejs
const sdk = require('node-appwrite');

const client = new sdk.Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('<PROJECT_ID>') // Your project ID
    .setKey('<API_KEY>'); // Your secret API key

const tablesDB = new sdk.TablesDB(client);

const result = await tablesDB.decrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 5 // value
});
```
```server-python
from appwrite.client import Client
from appwrite.services.tables_db import TablesDB

client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<PROJECT_ID>') # Your project ID
client.set_key('<API_KEY>') # Your secret API key

tablesDB = TablesDB(client)

result = tablesDB.decrement_row_column(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    column = 'credits', # column
    value = 5 # value
)
```
```rust
use appwrite::Client;
use appwrite::services::tables_db::TablesDB;

let client = Client::new()
    .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
    .set_project("<PROJECT_ID>")
    .set_key("<API_KEY>");

let tables_db = TablesDB::new(&client);

let result = tables_db.decrement_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "credits",     // column
    Some(5.0),     // value
    None,          // min
    None,          // transaction_id
).await?;
```
```graphql
mutation {
    databasesDecrementRowColumn(
        databaseId: "<DATABASE_ID>",
        tableId: "<TABLE_ID>",
        rowId: "<ROW_ID>",
        column: "credits",
        value: 5
    ) {
        _id
        _tableId
        _databaseId
        _createdAt
        _updatedAt
        _permissions
        data
    }
}
```
{% /multicode %}

# Set constraints and bounds {% #set-constraints-and-bounds %}

You can set minimum and maximum bounds for individual operations to prevent invalid values. Use the optional `min` and `max` parameters to ensure the final value stays within acceptable limits:

## Example with constraints {% #example-with-constraints %}

{% multicode %}
```client-web
// Increment with maximum constraint
const result = await tablesDB.incrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 100, // value
    max: 1000 // max (optional)
});

// Decrement with minimum constraint
const result2 = await tablesDB.decrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 50, // value
    min: 0 // min (optional)
});
```
```client-flutter
// Increment with maximum constraint
final row = await tablesDB.incrementRowColumn(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits',
    value: 100,
    max: 1000
);

// Decrement with minimum constraint
final row2 = await tablesDB.decrementRowColumn(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits',
    value: 50,
    min: 0
);
```
```client-apple
// Increment with maximum constraint
let row = try await tablesDB.incrementRowColumn(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    column: "credits",
    value: 100,
    max: 1000
)

// Decrement with minimum constraint
let row2 = try await tablesDB.decrementRowColumn(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    column: "credits",
    value: 50,
    min: 0
)
```
```client-android-kotlin
// Increment with maximum constraint
val row = tablesDB.incrementRowColumn(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    column = "credits",
    value = 100,
    max = 1000
)

// Decrement with minimum constraint
val row2 = tablesDB.decrementRowColumn(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    column = "credits",
    value = 50,
    min = 0
)
```
```server-nodejs
// Increment with maximum constraint
const result = await tablesDB.incrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 100, // value
    max: 1000 // max (optional)
});

// Decrement with minimum constraint
const result2 = await tablesDB.decrementRowColumn({
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'credits', // column
    value: 50, // value
    min: 0 // min (optional)
});
```
```server-python
# Increment with maximum constraint
result = tablesDB.increment_row_column(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    column = 'credits', # column
    value = 100, # value
    max = 1000 # max (optional)
)

# Decrement with minimum constraint
result2 = tablesDB.decrement_row_column(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    column = 'credits', # column
    value = 50, # value
    min = 0 # min (optional)
)
```
```rust
// Increment with maximum constraint
let result = tables_db.increment_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "credits",       // column
    Some(100.0),     // value
    Some(1000.0),    // max (optional)
    None,            // transaction_id
).await?;

// Decrement with minimum constraint
let result2 = tables_db.decrement_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "credits",       // column
    Some(50.0),      // value
    Some(0.0),       // min (optional)
    None,            // transaction_id
).await?;
```
{% /multicode %}

# Follow best practices {% #follow-best-practices %}

## Use for high-concurrency scenarios {% #use-for-high-concurrency-scenarios %}

Atomic numeric operations are most beneficial when multiple users or processes might update the same numeric field simultaneously.

## Combine with regular updates {% #combine-with-regular-updates %}

For complex updates that include both atomic operations and regular field changes, you'll need to use separate API calls:

{% multicode %}
```client-web
// First, increment the likes atomically
const likeResult = await tablesDB.incrementRowColumn(
    '<DATABASE_ID>',
    '<TABLE_ID>',
    '<ROW_ID>',
    'likes', // column
    1 // value
);

// Then, update other fields
const updateResult = await tablesDB.updateRow(
    '<DATABASE_ID>',
    '<TABLE_ID>',
    '<ROW_ID>',
    {
        lastLikedBy: userId,
        lastLikedAt: new Date().toISOString()
    }
);
```
```client-flutter
// First, increment the likes atomically
final likeResult = await tablesDB.incrementRowColumn(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    column: 'likes',
    value: 1
);

// Then, update other fields
final updateResult = await tablesDB.updateRow(
    databaseId: '<DATABASE_ID>',
    tableId: '<TABLE_ID>',
    rowId: '<ROW_ID>',
    data: {
        'lastLikedBy': userId,
        'lastLikedAt': DateTime.now().toIso8601String()
    }
);
```
```client-apple
// First, increment the likes atomically
let likeResult = try await tablesDB.incrementRowColumn(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    column: "likes",
    value: 1
)

// Then, update other fields
let updateResult = try await tablesDB.updateRow(
    databaseId: "<DATABASE_ID>",
    tableId: "<TABLE_ID>",
    rowId: "<ROW_ID>",
    data: [
        "lastLikedBy": userId,
        "lastLikedAt": ISO8601DateFormatter().string(from: Date())
    ]
)
```
```client-android-kotlin
// First, increment the likes atomically
val likeResult = tablesDB.incrementRowColumn(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    column = "likes",
    value = 1
)

// Then, update other fields
val updateResult = tablesDB.updateRow(
    databaseId = "<DATABASE_ID>",
    tableId = "<TABLE_ID>",
    rowId = "<ROW_ID>",
    data = mapOf(
        "lastLikedBy" to userId,
        "lastLikedAt" to Instant.now().toString()
    )
)
```
```server-nodejs
// First, increment the likes atomically
const likeResult = await tablesDB.incrementRowColumn(
    '<DATABASE_ID>',
    '<TABLE_ID>',
    '<ROW_ID>',
    'likes', // column
    1 // value
);

// Then, update other fields
const updateResult = await tablesDB.updateRow(
    '<DATABASE_ID>',
    '<TABLE_ID>',
    '<ROW_ID>',
    {
        lastLikedBy: userId,
        lastLikedAt: new Date().toISOString()
    }
);
```
```server-python
# First, increment the likes atomically
like_result = tablesDB.increment_row_column(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    column = 'likes', # column
    value = 1 # value
)

# Then, update other fields
update_result = tablesDB.update_row(
    database_id = '<DATABASE_ID>',
    table_id = '<TABLE_ID>',
    row_id = '<ROW_ID>',
    data = {
        'lastLikedBy': user_id,
        'lastLikedAt': datetime.now().isoformat()
    }
)
```
```rust
use serde_json::json;

// First, increment the likes atomically
let like_result = tables_db.increment_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "likes",       // column
    Some(1.0),     // value
    None,          // max
    None,          // transaction_id
).await?;

// Then, update other fields
let update_result = tables_db.update_row(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    Some(json!({
        "lastLikedBy": user_id,
        "lastLikedAt": chrono::Utc::now().to_rfc3339()
    })),
    None,          // permissions
    None,          // transaction_id
).await?;
```
{% /multicode %}

# Use transactions {% #use-transactions %}

Atomic numeric operations accept `transactionId`. When provided, increments/decrements are staged and applied on commit.

{% multicode %}
```client-web
await tablesDB.incrementRowColumn({
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
});
```
```client-flutter
await tablesDB.incrementRowColumn(
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
);
```
```client-apple
try await tablesDB.incrementRowColumn(
  databaseId: "<DATABASE_ID>",
  tableId: "<TABLE_ID>",
  rowId: "<ROW_ID>",
  column: "likes",
  value: 1,
  transactionId: "<TRANSACTION_ID>"
)
```
```client-android-kotlin
tablesDB.incrementRowColumn(
  databaseId = "<DATABASE_ID>",
  tableId = "<TABLE_ID>",
  rowId = "<ROW_ID>",
  column = "likes",
  value = 1,
  transactionId = "<TRANSACTION_ID>"
)
```
```client-android-java
tablesDB.incrementRowColumn(
  "<DATABASE_ID>",
  "<TABLE_ID>",
  "<ROW_ID>",
  "likes",
  1,
  "<TRANSACTION_ID>",
  new CoroutineCallback<>((result, error) -> {
    if (error != null) {
      error.printStackTrace();
      return null;
    }
    System.out.println(result);
    return null;
  })
);
```
```client-react-native
await tablesDB.incrementRowColumn({
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
});
```
```server-nodejs
await tablesDB.incrementRowColumn({
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
});
```
```server-deno
await tablesDB.incrementRowColumn({
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
});
```
```server-python
tablesDB.increment_row_column(
  database_id = '<DATABASE_ID>',
  table_id = '<TABLE_ID>',
  row_id = '<ROW_ID>',
  column = 'likes',
  value = 1,
  transaction_id = '<TRANSACTION_ID>'
)
```
```rust
tables_db.increment_row_column(
    "<DATABASE_ID>",
    "<TABLE_ID>",
    "<ROW_ID>",
    "likes",
    Some(1.0),
    None,                          // max
    Some("<TRANSACTION_ID>"),      // transaction_id
).await?;
```
```server-php
$tablesDB->incrementRowColumn(
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
);
```
```server-ruby
tablesDB.increment_row_column(
  database_id: '<DATABASE_ID>',
  table_id: '<TABLE_ID>',
  row_id: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transaction_id: '<TRANSACTION_ID>'
)
```
```server-dotnet
await tablesDB.IncrementRowColumn(
  databaseId: "<DATABASE_ID>",
  tableId: "<TABLE_ID>",
  rowId: "<ROW_ID>",
  column: "likes",
  value: 1,
  transactionId: "<TRANSACTION_ID>"
);
```
```server-dart
await tablesDB.incrementRowColumn(
  databaseId: '<DATABASE_ID>',
  tableId: '<TABLE_ID>',
  rowId: '<ROW_ID>',
  column: 'likes',
  value: 1,
  transactionId: '<TRANSACTION_ID>'
);
```
```server-swift
try await tablesDB.incrementRowColumn(
  databaseId: "<DATABASE_ID>",
  tableId: "<TABLE_ID>",
  rowId: "<ROW_ID>",
  column: "likes",
  value: 1,
  transactionId: "<TRANSACTION_ID>"
)
```
```server-kotlin
tablesDB.incrementRowColumn(
  databaseId = "<DATABASE_ID>",
  tableId = "<TABLE_ID>",
  rowId = "<ROW_ID>",
  column = "likes",
  value = 1,
  transactionId = "<TRANSACTION_ID>"
)
```
```server-java
tablesDB.incrementRowColumn(
  "<DATABASE_ID>",
  "<TABLE_ID>",
  "<ROW_ID>",
  "likes",
  1,
  "<TRANSACTION_ID>",
  new CoroutineCallback<>((result, error) -> {
    if (error != null) {
      error.printStackTrace();
      return null;
    }
    System.out.println(result);
    return null;
  })
);
```
{% /multicode %}

## Explore related features

- [Bulk operations](/docs/products/databases/bulk-operations) - Update multiple rows at once
- [Permissions](/docs/products/databases/permissions) - Control access to rows
- [Queries](/docs/products/databases/queries) - Find rows to update
- [Relationships](/docs/products/databases/relationships) - Update related rows
