> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powersync.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing Data

> Write data to the local SQLite database and manage the upload queue with the PowerSync SDK.

Write data using SQL `INSERT`, `UPDATE`, or `DELETE` statements. PowerSync automatically queues these writes and uploads them to your backend via the `uploadData()` function in your [backend connector](/intro/setup-guide#connect-to-powersync-service-instance).

## Basic Write Operations

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Insert a new todo
  await db.execute(
    'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)',
    [listId, 'Buy groceries']
  );

  // Update a todo
  await db.execute(
    'UPDATE todos SET completed = 1, completed_at = date() WHERE id = ?',
    [todoId]
  );

  // Delete a todo
  await db.execute('DELETE FROM todos WHERE id = ?', [todoId]);
  ```

  ```kotlin Kotlin theme={null}
  // Insert a new todo
  database.writeTransaction {
    database.execute(
      sql = "INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)",
      parameters = listOf(listId, "Buy groceries")
    )
  }

  // Update a todo
  database.execute(
    sql = "UPDATE todos SET completed = 1, completed_at = date() WHERE id = ?",
    parameters = listOf(todoId)
  )

  // Delete a todo
  database.execute(
    sql = "DELETE FROM todos WHERE id = ?",
    parameters = listOf(todoId)
  )
  ```

  ```swift Swift theme={null}
  // Insert a new todo
  try await db.execute(
    sql: "INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)",
    parameters: [listId, "Buy groceries"]
  )

  // Update a todo
  try await db.execute(
    sql: "UPDATE todos SET completed = 1, completed_at = date() WHERE id = ?",
    parameters: [todoId]
  )

  // Delete a todo
  try await db.execute(
    sql: "DELETE FROM todos WHERE id = ?",
    parameters: [todoId]
  )
  ```

  ```dart Dart/Flutter theme={null}
  // Insert a new todo
  await db.execute(
    'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)',
    [listId, 'Buy groceries']
  );

  // Update a todo
  await db.execute(
    'UPDATE todos SET completed = 1, completed_at = date() WHERE id = ?',
    [todoId]
  );

  // Delete a todo
  await db.execute('DELETE FROM todos WHERE id = ?', [todoId]);
  ```

  ```csharp .NET theme={null}
  // Insert a new todo
  await db.Execute(
    "INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), datetime(), ?, ?)",
    new[] { listId, "Buy groceries" }
  );

  // Update a todo
  await db.Execute(
    "UPDATE todos SET completed = 1, completed_at = datetime() WHERE id = ?",
    new[] { todoId }
  );

  // Delete a todo
  await db.Execute(
    "DELETE FROM todos WHERE id = ?", 
    new[] { todoId }
  );
  ```
</CodeGroup>

<Note>
  **Best practice**: Use UUIDs when inserting new rows on the client side. UUIDs can be generated offline/locally, allowing for unique identification of records created in the client database before they are synced to the server. See [Client ID](/sync/advanced/client-id) for more details.
</Note>

## ORM Support

PowerSync integrates with popular ORM libraries, which provide type safety and additional tooling. Using an ORM is often preferable to writing raw SQL queries, especially for common operations.

See [ORM Support](/client-sdks/orms/overview) to learn which ORMs PowerSync supports and how to get started.

## Write Operations and Upload Queue

PowerSync automatically queues writes and uploads them to your backend. The upload queue stores three types of operations:

| Operation | Purpose             | Contents                                                 | SQLite Statement                  |
| --------- | ------------------- | -------------------------------------------------------- | --------------------------------- |
| `PUT`     | Create new row      | Contains the value for each non-null column              | Generated by `INSERT` statements. |
| `PATCH`   | Update existing row | Contains the row `id`, and value of each changed column. | Generated by `UPDATE` statements. |
| `DELETE`  | Delete existing row | Contains the row `id`                                    | Generated by `DELETE` statements. |

The SDK automatically processes this queue by calling your `uploadData()` function. For a detailed breakdown of when and how `uploadData()` is called, including triggers, throttling, retry behavior, and error handling, see [When `uploadData()` is Called](/configuration/app-backend/client-side-integration#when-uploaddata-is-called).

For details on how to structure your backend to accept these writes, see [Writing Client Changes](/handling-writes/writing-client-changes).

## Advanced Topics

* [Usage Examples](/client-sdks/usage-examples) - Code examples for common use cases
