---
description: Learn how to use TypeORM with Capacitor and SQLite for decorator-based entity modeling and repository-driven data access in your mobile apps.
title: How to Use TypeORM with Capacitor and SQLite - Capawesome
image: https://capawesome.io/docs/assets/images/social/blog/how-to-use-typeorm-with-capacitor-and-sqlite.png
---

[ Skip to content](#how-to-use-typeorm-with-capacitor-and-sqlite) 

[ 🎉 Introducing **Capawesome Platform** — one platform for Live Updates, Native Builds, App Store Publishing, and Insider SDKs.](https://capawesome.io) 

* [  Formbricks ](/docs/plugins/formbricks/)
* [  Geocoder ](/docs/plugins/geocoder/)
* [  Google Sign-In ](/docs/plugins/google-sign-in/)
* [  libSQL ](/docs/plugins/libsql/)
* [  Live Update ](/docs/plugins/live-update/)
* [  Managed Configurations ](/docs/plugins/managed-configurations/)
* [  Media Session ](/docs/plugins/media-session/)
* [  ML Kit ](/docs/plugins/mlkit/)
* [  NFC ](/docs/plugins/nfc/)
* [  OAuth ](/docs/plugins/oauth/)
* [  Pedometer ](/docs/plugins/pedometer/)
* [  Photo Editor ](/docs/plugins/photo-editor/)
* [  PostHog ](/docs/plugins/posthog/)
* [  Printer ](/docs/plugins/printer/)
* [  Purchases ](/docs/plugins/purchases/)
* [  RealtimeKit ](/docs/plugins/realtimekit/)
* [  Screen Orientation ](/docs/plugins/screen-orientation/)
* [  Screenshot ](/docs/plugins/screenshot/)
* [  Secure Preferences ](/docs/plugins/secure-preferences/)
* [  Speech Recognition ](/docs/plugins/speech-recognition/)
* [  Speech Synthesis ](/docs/plugins/speech-synthesis/)
* [  Share Target ](/docs/plugins/share-target/)
* [  Square Mobile Payments ](/docs/plugins/square-mobile-payments/)
* [  SQLite ](/docs/plugins/sqlite/)
* [  Superwall ](/docs/plugins/superwall/)
* [  Torch ](/docs/plugins/torch/)
* [  Wifi ](/docs/plugins/wifi/)
* [  Zip ](/docs/plugins/zip/)
* [  Cloud ](/docs/cloud/)
* [  Live Updates ](/docs/cloud/live-updates/)
* Advanced
* Integrations
* [  Native Builds ](/docs/cloud/native-builds/)
* [  Configuration ](/docs/cloud/native-builds/configuration/)
* [  Environments ](/docs/cloud/native-builds/environments/)
* Guides
* [  Sample Projects ](/docs/cloud/native-builds/sample-projects/)
* [  Troubleshooting ](/docs/cloud/native-builds/troubleshooting/)
* [  Automations ](/docs/cloud/automations/)
* [  Assist ](/docs/cloud/assist/)
* Account
* Organizations
* [  Organization and User Management ](/docs/cloud/organizations/memberships/)
* [  Single Sign-On (SSO) ](/docs/cloud/organizations/sso/)
* [  Teams ](/docs/cloud/organizations/teams/)
* [  Two-Factor Authentication ](/docs/cloud/organizations/two-factor-authentication/)
* [  Integrations ](/docs/cloud/integrations/)
* [  License Keys ](/docs/cloud/license-keys/)
* [  Webhooks ](/docs/cloud/webhooks/)
* [  Pricing ](https://capawesome.io/pricing/)
* [  FAQ ](/docs/cloud/faq/)
* [  Support ](/docs/cloud/support/)
* [  Contributing ](/docs/contributing/)
* [  LLMs ](/docs/llms/)
* [  Insiders ](/docs/insiders/)
* [  License ](https://capawesome.io/legal/eula/)
* [  Support ](/docs/insiders/support/)
* [  FAQ ](/docs/insiders/faq/)
* [  Blog ](/blog/)
* Categories

* [  Transactions ](#transactions)
* [  Migrations ](#migrations)
* [  Stay Updated ](#stay-updated)
* [  Conclusion ](#conclusion)

* Related links

# How to Use TypeORM with Capacitor and SQLite[¶](#how-to-use-typeorm-with-capacitor-and-sqlite "Permanent link")

Many developers already use TypeORM on the backend to manage databases with TypeScript decorators and a familiar repository pattern. The good news: the same approach works in Capacitor apps too. The [Capacitor SQLite](/docs/plugins/sqlite/) plugin ships with a built-in `SQLiteConnection` class that plugs directly into TypeORM's `DataSource` — no additional adapter package required. This guide walks you through the complete setup, from defining entities to running queries and managing migrations.

For raw API usage, see the [Capacitor SQLite plugin documentation](/docs/plugins/sqlite/#api).

[ ![Build and deploy your Capacitor app with Capawesome Cloud](../../assets/external/cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.69628c3f.png) ](/) 

## What is TypeORM?[¶](#what-is-typeorm "Permanent link")

[TypeORM](https://typeorm.io/) is one of the most widely used ORMs in the TypeScript ecosystem. It takes a decorator-based approach to database modeling: you define your tables as classes, annotate columns and relationships with decorators, and interact with data through repositories and query builders.

Here's why it pairs well with Capacitor apps:

* **Decorator-based entities** — Tables are modeled as regular TypeScript classes. Columns, primary keys, and relationships are declared with decorators like `@Column()` and `@ManyToOne()`.
* **Repository pattern** — Each entity gets a repository with built-in methods for common operations (`find`, `save`, `remove`), so you rarely need to write SQL.
* **Automatic schema sync** — During development, TypeORM can synchronize your database schema with your entity definitions automatically.
* **Migration support** — For production, TypeORM provides a migration system to apply schema changes incrementally.
* **Wide adoption** — TypeORM has a large community and extensive documentation, which means answers to most questions are a search away.

## Prerequisites[¶](#prerequisites "Permanent link")

Before you begin, make sure you have a Capacitor project with the [SQLite](/docs/plugins/sqlite/) plugin installed. To install the plugin, please refer to the [Installation](/docs/plugins/sqlite/#installation) section in the plugin documentation.

## Installation[¶](#installation "Permanent link")

Since the TypeORM driver is included in the [SQLite](/docs/plugins/sqlite/) plugin itself, you only need to install TypeORM and its peer dependency:

`[](#%5F%5Fcodelineno-0-1)npm install typeorm reflect-metadata
`

TypeORM relies on decorators and metadata reflection, so you need to enable both in your `tsconfig.json`:

`[](#%5F%5Fcodelineno-1-1){
[](#%5F%5Fcodelineno-1-2)  "compilerOptions": {
[](#%5F%5Fcodelineno-1-3)    "experimentalDecorators": true,
[](#%5F%5Fcodelineno-1-4)    "emitDecoratorMetadata": true
[](#%5F%5Fcodelineno-1-5)  }
[](#%5F%5Fcodelineno-1-6)}
`

Finally, import `reflect-metadata` once at the entry point of your app (e.g. `main.ts`), before any other imports:

`[](#%5F%5Fcodelineno-2-1)import 'reflect-metadata';
`

## Configuring the DataSource[¶](#configuring-the-datasource "Permanent link")

TypeORM uses a `DataSource` to manage the database connection. To connect it to the [SQLite](/docs/plugins/sqlite/) plugin, pass an `SQLiteConnection` instance as the `driver`:

`[](#%5F%5Fcodelineno-3-1)import { Sqlite, SQLiteConnection } from '@capawesome-team/capacitor-sqlite';
[](#%5F%5Fcodelineno-3-2)import { DataSource } from 'typeorm';
[](#%5F%5Fcodelineno-3-3)
[](#%5F%5Fcodelineno-3-4)const AppDataSource = new DataSource({
[](#%5F%5Fcodelineno-3-5)  type: 'capacitor',
[](#%5F%5Fcodelineno-3-6)  driver: new SQLiteConnection(Sqlite),
[](#%5F%5Fcodelineno-3-7)  database: 'my-app',
[](#%5F%5Fcodelineno-3-8)  entities: [],
[](#%5F%5Fcodelineno-3-9)  synchronize: true,
[](#%5F%5Fcodelineno-3-10)  logging: ['error', 'schema'],
[](#%5F%5Fcodelineno-3-11)  migrationsRun: false,
[](#%5F%5Fcodelineno-3-12)});
`

A few things to note here:

* `type: 'capacitor'` tells TypeORM to use its built-in Capacitor driver, which delegates database operations to the provided `driver` instance.
* `driver: new SQLiteConnection(Sqlite)` bridges TypeORM to the Capacitor SQLite plugin. The `SQLiteConnection` class handles opening, closing, and routing queries to the correct database.
* `database` is the name used to identify the database file.
* `synchronize: true` automatically creates and updates tables based on your entities. This is convenient during development but should be disabled in production.
* `migrationsRun: false` is required when using the `capacitor` type.

To initialize the connection when your app starts:

`[](#%5F%5Fcodelineno-4-1)await AppDataSource.initialize();
`

## Defining Entities[¶](#defining-entities "Permanent link")

TypeORM models database tables as classes decorated with `@Entity()`. Each property that maps to a column is annotated with a decorator like `@PrimaryGeneratedColumn()` or `@Column()`.

`[](#%5F%5Fcodelineno-5-1)import {
[](#%5F%5Fcodelineno-5-2)  Entity,
[](#%5F%5Fcodelineno-5-3)  PrimaryGeneratedColumn,
[](#%5F%5Fcodelineno-5-4)  Column,
[](#%5F%5Fcodelineno-5-5)  ManyToOne,
[](#%5F%5Fcodelineno-5-6)  OneToMany,
[](#%5F%5Fcodelineno-5-7)  CreateDateColumn,
[](#%5F%5Fcodelineno-5-8)} from 'typeorm';
[](#%5F%5Fcodelineno-5-9)
[](#%5F%5Fcodelineno-5-10)@Entity()
[](#%5F%5Fcodelineno-5-11)export class User {
[](#%5F%5Fcodelineno-5-12)  @PrimaryGeneratedColumn()
[](#%5F%5Fcodelineno-5-13)  id!: number;
[](#%5F%5Fcodelineno-5-14)
[](#%5F%5Fcodelineno-5-15)  @Column('text')
[](#%5F%5Fcodelineno-5-16)  name!: string;
[](#%5F%5Fcodelineno-5-17)
[](#%5F%5Fcodelineno-5-18)  @Column({ type: 'text', unique: true })
[](#%5F%5Fcodelineno-5-19)  email!: string;
[](#%5F%5Fcodelineno-5-20)
[](#%5F%5Fcodelineno-5-21)  @CreateDateColumn()
[](#%5F%5Fcodelineno-5-22)  createdAt!: Date;
[](#%5F%5Fcodelineno-5-23)
[](#%5F%5Fcodelineno-5-24)  @OneToMany(() => Post, (post) => post.author)
[](#%5F%5Fcodelineno-5-25)  posts!: Post[];
[](#%5F%5Fcodelineno-5-26)}
[](#%5F%5Fcodelineno-5-27)
[](#%5F%5Fcodelineno-5-28)@Entity()
[](#%5F%5Fcodelineno-5-29)export class Post {
[](#%5F%5Fcodelineno-5-30)  @PrimaryGeneratedColumn()
[](#%5F%5Fcodelineno-5-31)  id!: number;
[](#%5F%5Fcodelineno-5-32)
[](#%5F%5Fcodelineno-5-33)  @Column('text')
[](#%5F%5Fcodelineno-5-34)  title!: string;
[](#%5F%5Fcodelineno-5-35)
[](#%5F%5Fcodelineno-5-36)  @Column({ type: 'text', nullable: true })
[](#%5F%5Fcodelineno-5-37)  content!: string | null;
[](#%5F%5Fcodelineno-5-38)
[](#%5F%5Fcodelineno-5-39)  @ManyToOne(() => User, (user) => user.posts)
[](#%5F%5Fcodelineno-5-40)  author!: User;
[](#%5F%5Fcodelineno-5-41)}
`

A few things to note:

* `@PrimaryGeneratedColumn()` creates an auto-incrementing primary key.
* `@Column()` accepts a type string or an options object for constraints like `unique` and `nullable`.
* `@CreateDateColumn()` automatically sets the current timestamp when a row is inserted.
* `@OneToMany()` and `@ManyToOne()` define the relationship between `User` and `Post`. TypeORM uses these to generate foreign keys and enable eager/lazy loading.

Don't forget to register your entities in the `DataSource` configuration:

`[](#%5F%5Fcodelineno-6-1)const AppDataSource = new DataSource({
[](#%5F%5Fcodelineno-6-2)  // ...
[](#%5F%5Fcodelineno-6-3)  entities: [User, Post],
[](#%5F%5Fcodelineno-6-4)});
`

## Working with Repositories[¶](#working-with-repositories "Permanent link")

TypeORM's repository pattern provides a high-level API for data access. Each entity gets its own repository with built-in methods for the most common operations.

### Insert[¶](#insert "Permanent link")

`[](#%5F%5Fcodelineno-7-1)const userRepo = AppDataSource.getRepository(User);
[](#%5F%5Fcodelineno-7-2)
[](#%5F%5Fcodelineno-7-3)const user = userRepo.create({
[](#%5F%5Fcodelineno-7-4)  name: 'Alice',
[](#%5F%5Fcodelineno-7-5)  email: 'alice@example.com',
[](#%5F%5Fcodelineno-7-6)});
[](#%5F%5Fcodelineno-7-7)await userRepo.save(user);
`

The `create()` method instantiates an entity without persisting it. Calling `save()` writes it to the database and populates the generated `id`.

### Select[¶](#select "Permanent link")

`[](#%5F%5Fcodelineno-8-1)// Find all users
[](#%5F%5Fcodelineno-8-2)const allUsers = await userRepo.find();
[](#%5F%5Fcodelineno-8-3)
[](#%5F%5Fcodelineno-8-4)// Find with a condition
[](#%5F%5Fcodelineno-8-5)const user = await userRepo.findOneBy({
[](#%5F%5Fcodelineno-8-6)  email: 'alice@example.com',
[](#%5F%5Fcodelineno-8-7)});
[](#%5F%5Fcodelineno-8-8)
[](#%5F%5Fcodelineno-8-9)// Find with relations
[](#%5F%5Fcodelineno-8-10)const userWithPosts = await userRepo.findOne({
[](#%5F%5Fcodelineno-8-11)  where: { id: 1 },
[](#%5F%5Fcodelineno-8-12)  relations: { posts: true },
[](#%5F%5Fcodelineno-8-13)});
`

### Update[¶](#update "Permanent link")

`[](#%5F%5Fcodelineno-9-1)await userRepo.update({ id: 1 }, { name: 'Bob' });
`

### Delete[¶](#delete "Permanent link")

`[](#%5F%5Fcodelineno-10-1)await userRepo.delete({ id: 1 });
`

For more complex queries, TypeORM also offers a `QueryBuilder` that supports joins, subqueries, and aggregations:

`[](#%5F%5Fcodelineno-11-1)const users = await userRepo
[](#%5F%5Fcodelineno-11-2)  .createQueryBuilder('user')
[](#%5F%5Fcodelineno-11-3)  .leftJoinAndSelect('user.posts', 'post')
[](#%5F%5Fcodelineno-11-4)  .where('user.name LIKE :name', { name: '%Ali%' })
[](#%5F%5Fcodelineno-11-5)  .getMany();
`

## Transactions[¶](#transactions "Permanent link")

When multiple operations need to succeed or fail as a unit, wrap them in a transaction:

`[](#%5F%5Fcodelineno-12-1)await AppDataSource.transaction(async (manager) => {
[](#%5F%5Fcodelineno-12-2)  const user = manager.create(User, {
[](#%5F%5Fcodelineno-12-3)    name: 'Alice',
[](#%5F%5Fcodelineno-12-4)    email: 'alice@example.com',
[](#%5F%5Fcodelineno-12-5)  });
[](#%5F%5Fcodelineno-12-6)  await manager.save(user);
[](#%5F%5Fcodelineno-12-7)
[](#%5F%5Fcodelineno-12-8)  const post = manager.create(Post, {
[](#%5F%5Fcodelineno-12-9)    title: 'Hello World',
[](#%5F%5Fcodelineno-12-10)    content: '...',
[](#%5F%5Fcodelineno-12-11)    author: user,
[](#%5F%5Fcodelineno-12-12)  });
[](#%5F%5Fcodelineno-12-13)  await manager.save(post);
[](#%5F%5Fcodelineno-12-14)});
`

If any operation inside the callback throws, the entire transaction is rolled back. The `manager` parameter is a transactional `EntityManager` — use it instead of individual repositories to ensure all operations run within the same transaction.

## Migrations[¶](#migrations "Permanent link")

While `synchronize: true` is handy during development, it should not be used in production since it can lead to data loss. Instead, use TypeORM's migration system to apply schema changes incrementally.

### Writing Migrations[¶](#writing-migrations "Permanent link")

Create a migration class that implements `up` and `down` methods:

`` [](#%5F%5Fcodelineno-13-1)import { MigrationInterface, QueryRunner } from 'typeorm';
[](#%5F%5Fcodelineno-13-2)
[](#%5F%5Fcodelineno-13-3)export class CreateUsers1709000000000 implements MigrationInterface {
[](#%5F%5Fcodelineno-13-4)  async up(queryRunner: QueryRunner): Promise<void> {
[](#%5F%5Fcodelineno-13-5)    await queryRunner.query(`
[](#%5F%5Fcodelineno-13-6)      CREATE TABLE IF NOT EXISTS user (
[](#%5F%5Fcodelineno-13-7)        id INTEGER PRIMARY KEY AUTOINCREMENT,
[](#%5F%5Fcodelineno-13-8)        name TEXT NOT NULL,
[](#%5F%5Fcodelineno-13-9)        email TEXT NOT NULL UNIQUE,
[](#%5F%5Fcodelineno-13-10)        createdAt DATETIME DEFAULT (datetime('now'))
[](#%5F%5Fcodelineno-13-11)      )
[](#%5F%5Fcodelineno-13-12)    `);
[](#%5F%5Fcodelineno-13-13)  }
[](#%5F%5Fcodelineno-13-14)
[](#%5F%5Fcodelineno-13-15)  async down(queryRunner: QueryRunner): Promise<void> {
[](#%5F%5Fcodelineno-13-16)    await queryRunner.query(`DROP TABLE IF EXISTS user`);
[](#%5F%5Fcodelineno-13-17)  }
[](#%5F%5Fcodelineno-13-18)}
 ``

### Running Migrations[¶](#running-migrations "Permanent link")

Register your migrations in the `DataSource` and run them at startup:

`[](#%5F%5Fcodelineno-14-1)import { CreateUsers1709000000000 } from './migrations/CreateUsers1709000000000';
[](#%5F%5Fcodelineno-14-2)
[](#%5F%5Fcodelineno-14-3)const AppDataSource = new DataSource({
[](#%5F%5Fcodelineno-14-4)  type: 'capacitor',
[](#%5F%5Fcodelineno-14-5)  driver: new SQLiteConnection(Sqlite),
[](#%5F%5Fcodelineno-14-6)  database: 'my-app',
[](#%5F%5Fcodelineno-14-7)  entities: [User, Post],
[](#%5F%5Fcodelineno-14-8)  migrations: [CreateUsers1709000000000],
[](#%5F%5Fcodelineno-14-9)  synchronize: false,
[](#%5F%5Fcodelineno-14-10)  migrationsRun: false,
[](#%5F%5Fcodelineno-14-11)});
[](#%5F%5Fcodelineno-14-12)
[](#%5F%5Fcodelineno-14-13)await AppDataSource.initialize();
[](#%5F%5Fcodelineno-14-14)await AppDataSource.runMigrations();
`

TypeORM tracks which migrations have been applied in a `migrations` table, so calling `runMigrations()` repeatedly is safe — only pending migrations are executed.

## Stay Updated[¶](#stay-updated "Permanent link")

Want to stay up to date with the latest features and guides? Subscribe to the Capawesome newsletter.

[Subscribe to the Capawesome Newsletter](/newsletter/)

## Conclusion[¶](#conclusion "Permanent link")

TypeORM brings its decorator-based entity modeling and repository pattern to Capacitor apps through the built-in `SQLiteConnection` class in the [Capacitor SQLite plugin](/docs/plugins/sqlite/). There's no separate adapter to install — just configure a `DataSource` with `type: 'capacitor'`, define your entities as decorated classes, and use repositories for data access.

**Resources:**

* [API Reference](/docs/plugins/sqlite/#api)
* [Exploring the Capacitor SQLite API](/blog/exploring-the-capacitor-sqlite-api/)

**Related tutorials:** 

* If you prefer a lighter, SQL-first approach check [Drizzle ORM](/blog/how-to-use-drizzle-orm-with-capacitor-and-sqlite/) or [Kysely](/blog/how-to-use-kysely-with-capacitor-and-sqlite/)

If you have questions or feedback, join the [Capawesome Discord](https://discord.gg/VCXxSVjefW) server to connect with the community. And subscribe to the Capawesome [newsletter](/newsletter/) to stay updated on the latest news.

May 7, 2026 

 Back to top 