---
title: "Migrate PostgreSQL to SQLite in your browser"
description: "Migrate a PostgreSQL database to SQLite: convert a pg_dump file into a script with the same tables, keys and data, and a report of every change."
canonical: https://intosql.com/postgresql-to-sqlite
last_updated: 2026-10-15
---

# Migrate PostgreSQL to SQLite in your browser

Drop a plain dump from pg_dump or pg_dumpall, as .sql or .sql.gz, and download a script for SQLite with the same tables, keys, indexes and data. Every value SQLite can't hold as it is, and every object it doesn't carry, is listed in the report.

[PostgreSQL to SQLite migration guide](https://intosql.com/docs/migrations/postgresql-to-sqlite)

[PostgreSQL to SQLite data types](https://intosql.com/docs/types/postgresql-to-sqlite)

## What changes from PostgreSQL to SQLite

Each row is a rule the converter applies, with the report line it writes when the rule changes something in your data.

| In PostgreSQL | In SQLite | Report line |
| --- | --- | --- |
| boolean | INTEGER 0 or 1 with a CHECK |  |
| varchar(n), char(n), text | VARCHAR(n) and TEXT, not enforced |  |
| numeric(p,s) past 15 digits and numeric without a precision | TEXT | `decimal_as_text` |
| money | NUMERIC | `type_replaced` |
| interval | TEXT with PostgreSQL's text | `type_replaced` |
| arrays (integer[], text[]...) | TEXT with a JSON array | `type_replaced` |
| ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension types | TEXT with PostgreSQL's text | `type_replaced` |
| json, jsonb | TEXT |  |
| timestamp | DATETIME as ISO 8601 text |  |
| timestamp with time zone | TIMESTAMP as ISO 8601 text in UTC | `moments_as_utc` |
| time | TIME as text |  |
| infinity, -infinity and BC dates | NULL | `date_out_of_range` |
| NaN and Infinity in numeric, real and double precision | NULL | `invalid_value_null` |
| NOT NULL columns with values that become NULL | NOT NULL dropped | `not_null_relaxed` |
| enum types | TEXT with a CHECK of its labels |  |
| enum columns holding values outside their labels | TEXT without a check | `enum_check_skipped` |
| uuid, inet, cidr, macaddr | TEXT |  |
| bytea | BLOB |  |
| bit(n), bit varying | INTEGER with the bits' value up to 63 bits; TEXT digits beyond |  |
| oid, xid, cid | INTEGER with a CHECK that it isn't negative |  |
| citext and nondeterministic collations | exact comparison | `case_insensitive_collation` |
| serial, identity | INTEGER PRIMARY KEY AUTOINCREMENT, continuing after the highest id |  |
| serial and identity columns that aren't the whole primary key | INTEGER without a counter | `counter_dropped` |
| sequences not owned by a column | not created | `sequence_not_converted` |
| generated columns | GENERATED ALWAYS AS, STORED or VIRTUAL as in the source |  |
| generated columns with functions SQLite lacks | a plain column with the values | `generated_not_translated` |
| defaults with functions SQLite lacks, and defaults from a sequence | no default | `default_not_translated` |
| CHECK constraints | translated, inline in CREATE TABLE |  |
| CHECK constraints with functions SQLite lacks | not created | `check_skipped` |
| CHECK ... NOT VALID | not created | `check_not_valid` |
| gin, gist, brin and hash indexes, partial and expression indexes | not created | `index_skipped` |
| foreign keys | in CREATE TABLE, loaded unchecked, then listed by PRAGMA foreign_key_check |  |
| foreign keys to tables the dump doesn't create | not created | `foreign_key_skipped` |
| partitioned tables | one table with every partition's rows | `partitions_dropped` |
| schemas | one file, tables named after their schema first | `schemas_merged` |
| views, functions, procedures, triggers, rules, policies, extensions and types | listed in the report | `not_converted_objects` |
| dumps without CREATE TABLE (--data-only) | types read from the values | `no_schema` |
| expressions in INSERT values | NULL | `expression_value` |
| types IntoSQL doesn't know | TEXT | `unknown_type` |
| text that isn't valid in its encoding | the bad bytes as the replacement character | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | copied as it is | `mojibake_suspected` |

## Load the script into SQLite

The script creates the tables, copies the rows, then adds keys, indexes and foreign keys, so it loads fast and stops at the first error.

```shell
sqlite3 -bail mydb.sqlite < postgresql.sqlite.sql
```

Foreign keys are declared in each table and the rows load with foreign key checks off. The script then lists any row that points to a row that doesn't exist, instead of failing half way.

For a large dump, load into a new file on a local disk. The script loads everything in one transaction with syncing off, so it runs at disk speed, and a load that stops half way leaves no partial tables.

The command line loads the file straight into a SQLite database, without writing a script. It's free.

## Dump PostgreSQL for the best result

The converter reads what the dump holds. These options keep more of your data in it:

- --format=plain, pg_dump's default, writes SQL. A custom or directory archive (-Fc, -Fd) becomes SQL with pg_restore -f dump.sql, without a database server.
- --no-owner --no-privileges leave out roles and grants, which the converter skips anyway, so the dump is smaller.
- pg_dumpall dumps every database in one file; each one's tables are named after it, so nothing collides.

## What isn't converted

Views, materialized views, functions, procedures, triggers, rules, row security policies, extensions and types are written in PostgreSQL's own language. They are listed in the report by name, never dropped silently, so you can rewrite them for SQLite.

## Questions about PostgreSQL to SQLite

### Is my dump uploaded?

No. The converter runs in your browser and reads the dump from your disk in pieces, so it never leaves your computer. The desktop app and the command line convert on your computer too.

### How large can the dump be?

The converter never holds the whole dump in memory: it reads the file twice, by ranges, and writes the script as it goes. Multi-gigabyte dumps convert in the browser, in the desktop app and with the command line.

### Does it read pg_dump -Fc archives?

Not directly: a custom archive is a binary format. pg_restore -f dump.sql dump.backup turns it into the plain SQL the converter reads, without connecting to a server. The converter says so when it gets an archive.

### Which PostgreSQL versions can the dump come from?

Dumps written by pg_dump and pg_dumpall from PostgreSQL 10 on, with COPY or INSERT rows. Every test dump comes from PostgreSQL 13 and 18 and is compared with its source cell by cell.

### Are serial and identity values kept?

A serial or identity column that is the table's whole primary key becomes INTEGER PRIMARY KEY AUTOINCREMENT, every row keeps its id, and the next id continues after the highest one. Any other keeps its values without a counter, and the report says so.

### What happens to arrays, enums and other PostgreSQL types?

Arrays become JSON arrays, booleans 0 and 1, enums text with a check of their labels, and timestamps with a time zone UTC text. Wide numerics stay exact as text. Ranges, geometric types and composite types keep PostgreSQL's text.

### What about functions, triggers and views?

They are listed in the report by name and not converted, because each database writes them in its own language.

### Which SQLite versions does the script load on?

SQLite 3.31 and later. Every test dump loads on 3.31 and 3.54, stopping at the first error if anything goes wrong.

## From PostgreSQL

- [PostgreSQL to PostgreSQL](https://intosql.com/postgresql-to-postgresql)
- [PostgreSQL to MySQL](https://intosql.com/postgresql-to-mysql)
- [PostgreSQL to MariaDB](https://intosql.com/postgresql-to-mariadb)
- [PostgreSQL to SQL Server](https://intosql.com/postgresql-to-sql-server)
- [PostgreSQL to Oracle](https://intosql.com/postgresql-to-oracle)

## Into SQLite

- [MySQL to SQLite](https://intosql.com/mysql-to-sqlite)
- [MariaDB to SQLite](https://intosql.com/mariadb-to-sqlite)
- [SQL Server to SQLite](https://intosql.com/sql-server-to-sqlite)
- [SQLite to SQLite](https://intosql.com/sqlite-to-sqlite)
- [Oracle to SQLite](https://intosql.com/oracle-to-sqlite)

## Guide and every pair

- [SQLite to PostgreSQL](https://intosql.com/sqlite-to-postgresql)
- [PostgreSQL to SQLite migration guide](https://intosql.com/docs/migrations/postgresql-to-sqlite)
- [PostgreSQL to SQLite data types](https://intosql.com/docs/types/postgresql-to-sqlite)
- [Every database pair](https://intosql.com/database-migration)
