expo-sqlite
@amazon-devices/expo-sqlite gives your app access to a database that can be queried through a WebSQL-like API. The database is persisted across restarts of your app.
Installation
- Add the JavaScript library dependency in the package.jsonfile.dependencies: { ... "@amazon-devices/expo-sqlite": "~2.0.0", "@amazon-devices/keplerscript-turbomodule-api": "~1.0.0", "expo": "~50.0.0", ... }
- Reinstall dependencies using npm installcommand and rebuild your application with thekepler buildcommand.
Examples
The example below provides a comprehensive example showing full database operations flow in a typical application.
import {openDatabase, SQLResultSet} from '@amazon-devices/expo-sqlite';
import React, {useEffect, useState} from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
let db = openDatabase('database.db');
export const App = () => {
  const [rows, setRows] = useState<any[][]>([]);
  const [dbClosed, setDbClosed] = useState(false);
  // create the database
  useEffect(() => {
    db.transaction((tx) => {
      tx.executeSql(
        'create table if not exists items (id integer primary key not null, done int, value text, floating double, int integer);',
      );
    });
  }, []);
  const handleSelectResult = (result: SQLResultSet) => {
    if (result.rows.length > 0) {
      const columnNames = Object.keys(result.rows._array[0]);
      const allRows = result.rows._array.map(Object.values);
      setRows([columnNames, ...allRows]);
    } else {
      setRows([]);
    }
  };
  // open the database
  const openDb = () => {
    db = openDatabase('database.db');
    db.transaction((tx) => {
      tx.executeSql(
        'create table if not exists items (id integer primary key not null, done int, value text, floating double, int integer);',
      );
    });
    setDbClosed(false);
  };
  // synchronously close the database
  const closeDbSync = () => {
    db.closeSync();
    setDbClosed(true);
  };
  // asynchronously close the database
  const closeDbAsync = async () => {
    await db.closeAsync();
    setDbClosed(true);
  };
  // perform insert operation synchronously
  const transactionSync = () => {
    db.transaction((tx) => {
      const done = Math.round(Math.random());
      const value = 'text-' + Date.now().toString().slice(-4);
      const float = Number((Math.random() * 10).toFixed(2));
      const int = Math.round(Math.random() * 1000);
      tx.executeSql(
        'insert into items (done, value, floating, int) values (?, ?, ?, ?)',
        [done, value, float, int],
        () => {},
      );
    });
  };
  // perform delete operation asynchronously
  const transactionAsync = async () => {
    await db.transactionAsync(async (tx) => {
      await tx.executeSqlAsync(
        'delete from items where id = (select max(id) from items)',
      );
    });
  };
  // perform select transaction synchronously
  const readTransactionSync = () => {
    db.readTransaction((tx) => {
      tx.executeSql('select * from items', [], (_, result) =>
        handleSelectResult(result),
      );
    });
  };
  // drop the database
  const deleteDb = () => {
    db.deleteAsync();
  };
  return (
    <View style={styles.container}>
      <View style={styles.sideColumn}>
        <Button title="open" onPress={openDb} disabled={!dbClosed} />
        <Button title="close sync" onPress={closeDbSync} disabled={dbClosed} />
        <Button
          title="close async"
          onPress={closeDbAsync}
          disabled={dbClosed}
        />
        <Button
          title="transaction sync (insert)"
          onPress={transactionSync}
          disabled={dbClosed}
        />
        <Button
          title="transaction async (delete)"
          onPress={transactionAsync}
          disabled={dbClosed}
        />
        <Button
          title="read transaction sync (select)"
          onPress={readTransactionSync}
          disabled={dbClosed}
        />
        <Button
          title="delete database"
          onPress={deleteDb}
          disabled={!dbClosed}
        />
      </View>
      <View style={styles.mainColumn}>
        <Text style={styles.label}>Database version: {db.version}</Text>
        <Text style={styles.label}>Database open: {String(!dbClosed)}</Text>
        <View style={styles.table}>
          {rows.map((row) => (
            <View style={styles.row}>
              {row.map((col) => (
                <View style={styles.cell}>
                  <Text style={styles.cellText}>{String(col)}</Text>
                </View>
              ))}
            </View>
          ))}
        </View>
      </View>
    </View>
  );
};
const styles = StyleSheet.create({
  scrollView: {
    flex: 1,
  },
  container: {
    flex: 1,
    backgroundColor: 'white',
    flexDirection: 'row',
    padding: 20,
  },
  sideColumn: {
    flex: 1,
    flexDirection: 'column',
    padding: 10,
  },
  mainColumn: {
    flex: 2,
    flexDirection: 'column',
    padding: 10,
  },
  label: {
    color: 'black',
    fontSize: 32,
    flexDirection: 'column',
  },
  table: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    flexDirection: 'row',
    height: 40,
  },
  cell: {
    flex: 1,
    borderColor: 'black',
    borderWidth: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  cellText: {
    color: 'black',
    fontSize: 20,
  },
});
API reference
See the official Expo documentation.
Classes
| Class | Description | 
|---|---|
| ExpoSQLTransactionAsync | Internal data structure for the async transaction API | 
| SQLError | Class used for handling errors related to database operations | 
| SQLiteDatabase | The database returned by openDatabase() | 
SQLError properties
| Property | Description | 
|---|---|
| code | Error code | 
| message | Error message | 
| CONSTRAINT_ERR | This error code indicates a constraint violation | 
| DATABASE_ERR | This error code indicates a general error related to the database | 
| SYNTAX_ERR | This error code indicates a syntax error in the SQL statement | 
| TOO_LARGE_ERR | This error code indicates that the data being processed is too large to handle | 
| UNKNOWN_ERR | This error code indicates that and unknown or unexpected error has occured | 
| VERSION_ERR | This error code indicates a compatibility issue between the SQLite database version and the version expected by @amazon-devices/expo-sqlite | 
SQLiteDatabase properties
| Property | Description | 
|---|---|
| close | The method that can be used to close the database. WARNING: This method is deprecated and closeAsync()should be used instead | 
| version | The current version of the database | 
SQLiteDatabase methods
| Method | Description | 
|---|---|
| closeAsync | Closes the database | 
| deleteAsync | Delete the database file. The database has to be closed prior to deletion | 
| exec | Executes the SQL statement and returns a callback resolving with the result | 
| execAsync | Executes the SQL statement and returns a Promise resolving with the result | 
| readTransaction | Ensures the database is locked for reading only during the transaction | 
| transaction | Execute a database transaction | 
| transactionAsync | Creates a new transaction with Promise support | 
Methods
| Method | Description | 
|---|---|
| openDatabase | Open a database, creating it if it doesn't exist, and return a Databaseobject. On disk, the database will be created under the app's documents directory, i.e.${FileSystem.documentDirectory}/SQLite/${name} | 
Supported versions
| Package Version | Based On | @amazon-devices/react-native-kepler version | 
|---|---|---|
| 2.0.x | 11.8.0 | 2.0.x | 
Additional resources
For information on additional libraries, see Supported Third-Party Libraries and Services.
Last updated: Sep 30, 2025

