Migrate from Microsoft Access to PostgreSQL and Mathesar

Moving an Access database into PostgreSQL with Mathesar is mostly a data modeling and access-control job. This page covers what moves cleanly, what needs rework, and how to sequence the cutover.

On this page

Migrate from Microsoft Access to PostgreSQL and Mathesar: what the move involves

Moving a shared Access database to PostgreSQL means moving its tables into a server-based schema, then using Mathesar for everyday editing, browsing and forms. Most of the work is schema design, data typing and permissions, not application code. Access tables, indexes and relationships map to PostgreSQL tables, primary and foreign keys and constraints, while the front end is replaced by Mathesar's spreadsheet-like interface and its form builder. Access queries become PostgreSQL views, and VBA logic has to be rewritten as database functions, triggers or application code, which is often the largest unknown in the project.

The work is usually led by the internal database owner, the person who already knows what the Access file is used for, with an implementation partner handling the PostgreSQL setup, the migration scripts and the review of permissions. Before any table is moved, the owner should inventory every table, form, query and macro, record which fields hold attachments or multivalued data, and agree who may read and who may edit each table. Mathesar's access control follows PostgreSQL roles and privileges, so the role design should be settled early, and the reader should confirm with the Mathesar documentation how its current beta release handles those roles in their setup.

The main risks are data loss during export, type mismatches such as Access date and text fields loaded into the wrong PostgreSQL types, and permissions that are looser or tighter than intended. Plan a test run on a copy of the data, compare row counts and sample records table by table, and keep the original Access file read-only until users have signed off. Effort depends mainly on the number of VBA procedures and the volume of attachments, so ask any partner to size the work from a written inventory of the database rather than from a general estimate.

Which Access features map cleanly to PostgreSQL and Mathesar

This table compares common Access features with their PostgreSQL and Mathesar equivalents and marks each as clean, needs rework or gap. Read it before scoping the migration, because the rows marked needs rework or gap set most of the rebuild effort. Mathesar covers everyday table editing, forms and queries, but Access forms, reports and VBA logic still need to be rebuilt elsewhere.

Access featurePostgreSQL and Mathesar equivalentStatus
Tables and recordsPostgreSQL tables, imported through Mathesar or CSV, browsed and edited in Mathesar's spreadsheet-like gridClean
Data types (text, number, date, yes/no)Mapped to PostgreSQL types such as text, numeric, date and boolean; confirm precision and length choices per column before importClean
Primary keys and autonumberDeclared as PostgreSQL primary keys; Access AutoNumber becomes an integer identity or sequence that must be set up explicitlyNeeds rework
Relationships and lookupsForeign keys in PostgreSQL; Access lookup fields exported as IDs must be remapped to the referenced tableNeeds rework
Multivalued fieldsNo direct equivalent; normalize into a junction table, because Access multivalued fields do not survive a plain CSV exportNeeds rework
QueriesRebuilt as PostgreSQL views, or explored through Mathesar's Data Explorer for ad hoc queries; complex parameter queries need SQLNeeds rework
Forms and reportsMathesar's form builder covers data entry forms; Access reports and complex layouts must be rebuilt in another tool or application codeGap
VBA and macrosNot supported in PostgreSQL or Mathesar; move logic into database functions, triggers or application code, and confirm each routine individuallyGap
Attachments and OLE objectsMathesar offers a file data type, but Access attachments and OLE objects must be exported separately and linked, so confirm storage locationNeeds rework
User-level securityAccess-level permissions do not carry over; map users to PostgreSQL roles and privileges, which Mathesar uses for access controlNeeds rework

What data and integrations to move, and by which export path

An Access migration to PostgreSQL and Mathesar moves four kinds of content: table data, the schema that gives it meaning, queries and logic, and the links to files and other applications. Each needs its own export path, so inventory them before the first table is exported.

Table data as CSV

Access exports one object at a time, so each table or query is saved as its own file rather than a whole database in one step. Mathesar imports CSV with comma, tab, semicolon, colon or pipe delimiters, so choose a delimiter that never appears in your text fields and check the encoding of accented characters before the import. Confirm the row counts in Access and PostgreSQL match after each load.

Data types and primary keys

Map each Access field to a PostgreSQL type before import, because Access AutoNumber, Currency, Yes/No and Memo fields do not carry over unchanged. Decide which column becomes the primary key and confirm it has no duplicates, since PostgreSQL enforces this and Access may not have. Foreign keys should be recreated after the data loads so that referential errors surface as a clear list.

Attachments and OLE objects

Attachment fields and OLE objects are not part of a plain CSV export, so treat them as a separate workstream. Extract the files to a controlled file store on your servers, record their paths or identifiers in a text column, and check that every record points to a file that opens. Confirm with your Access administrator how many attachments exist and where they are stored before you plan storage.

Queries rebuilt as views

Access select queries become PostgreSQL views, and Access expressions must be rewritten in SQL. Start with the queries your reports and forms depend on, and test each view against a known result from Access. Action queries and VBA logic do not move automatically, so list them as separate items that need a design decision.

Roles and linked applications

Map who uses each table to a PostgreSQL role and grant only the privileges that role needs, because Mathesar applies access control through those roles. Linked Excel workbooks, reports, ODBC connections and other applications that read the Access file will break at cutover, so list each one and assign an owner to reconnect it to PostgreSQL.

The migration sequence from inventory to decommission

This sequence moves Access data into PostgreSQL and Mathesar in checked stages, so each table, rule and user is proven before Access is switched off. Each step ends with a written output that the next step depends on.

  1. Inventory tables, queries, forms and users

    Start by listing every table, query, form, report, macro and VBA module in the Access file, along with the people who open it and what they do with it. The database owner or a power user usually does this with the business owner, and an engineer checks the list for hidden dependencies such as linked tables, saved imports and reports that feed other files. The output is an inventory register with a row for each object, its owner, its record count and whether it is still used. The step is done when the business owner has signed off that nothing in use is missing.

  2. Design the PostgreSQL schema

    Translate the Access tables into PostgreSQL tables by mapping each Access field to a PostgreSQL data type, choosing primary keys and foreign keys, and deciding how multivalued fields, lookups and attachments will be stored, since Access attachments and OLE objects do not export as plain columns. A database engineer writes the schema in migration scripts and reviews it with the business owner. The output is a data dictionary and a mapping sheet that record each source field, its target type and any transformation. The step is done when every inventoried table has a mapped target and each open question has a recorded decision.

  3. Export and load a pilot copy

    Export the Access tables to CSV, one object at a time, and load them into a separate PostgreSQL database that is not used by anyone else. The pilot runs on a copy, so the live Access file stays untouched while the import is tested. Mathesar can connect to the pilot database, which lets the team see the tables in its spreadsheet-like interface. Mathesar imports CSV with comma, tab, semicolon, colon or pipe delimiters, so the team should confirm which delimiter and encoding the export produces before loading. The output is a reconciliation report that compares row counts and sample values per table against Access. The step is done when every table reconciles or each difference has a recorded cause.

  4. Rebuild queries as views and test them

    Recreate the logic of Access queries as PostgreSQL views, then run each view against the pilot data and compare the results with the same query in Access. Mathesar's Data Explorer can be used by the business owner to check results without writing SQL. Any VBA logic that cannot be expressed as a view needs to be moved to an application or a scheduled job, and that decision is recorded with the owner. The output is a query mapping list with a test result for each view and a note for each piece of logic that moved elsewhere. The step is done when the business owner accepts the results of every query in use.

  5. Set roles and sign off the role matrix

    Create PostgreSQL roles that match the groups identified in the inventory, grant privileges on the schemas, tables and views each group needs, and configure how users sign in, using the authentication methods the organization already supports. In Mathesar, the team can use existing roles or set up its own, and access then follows PostgreSQL privileges. A security reviewer tests that each role can do only what it should, including a check that read-only groups cannot edit. The output is a signed-off role matrix that lists each group, its privileges and the approver. The step is done when the test accounts behave as the matrix says.

  6. Run the parallel period and cut over

    Run Access and Mathesar side by side for a set period agreed in advance with the business owner. During this time Access can be made read-only, or kept in use with a daily comparison against PostgreSQL, while users work in Mathesar and report any difference. When the reconciliation is clean and the users have confirmed their forms and views, the team switches the live data to PostgreSQL and tells users where to edit records. The output is a cutover record that lists the final row counts, the date of the switch and the names of the people who approved it. The step is done when no open differences remain and the users confirm the new process.

  7. Decommission Access with an archived copy

    Once the cutover is stable, make a final archived copy of the Access file, the exports and the migration scripts, and store them in a read-only location on the organization's own servers, with a retention period set by the records owner. Remove the Access file and shortcuts from shared drives and document where the archive is held. Backups of the PostgreSQL database should be set up before the switch is closed, with restores tested. The output is a decommission record that lists the archive location, the retention owner and the removal date. The step is done when the archive can be opened and the record is signed by the business owner.

How the move differs by starting point

A single table shared by a few people is usually the shortest move. The data maps directly to one PostgreSQL table, and the main questions are about column types and who needs to edit rows. Most of the effort goes into cleaning the export and deciding the access model, since there are few relationships to rebuild.

  • Data types: Choose PostgreSQL types for each column, such as date, numeric or text, and check that Access Date/Time and Currency fields survive the CSV export.
  • Primary key: Access often has an AutoNumber field. Decide whether to keep it as an integer identity column or switch to a UUID if records come from several sources.
  • Roles: A few users can be given PostgreSQL roles with table-level privileges, and Mathesar then uses those roles for editing.
  • Attachments: If the table holds attachments or OLE objects, plan a separate storage location, because a CSV export does not carry them.
  • Forms: A simple data-entry form may be enough in Mathesar, so there is little or no application logic to rebuild.

Before you start, confirm with a test import that row counts and date values match the source, and that the people who edit the table have working accounts.

Setting PostgreSQL roles and running the database after cutover

Start by mapping Access user groups to PostgreSQL group roles before anyone edits data. Create one NOLOGIN group role per Access working group, such as accounts or intake, then grant that role the privileges it needs on each table or view with GRANT SELECT, INSERT, UPDATE statements, and add individual login roles to the groups they belong to. Keep editing rights on base tables narrow and give most staff read access through views, so a change to a query does not silently widen what someone can alter. Mathesar can use roles that already exist in the cluster or set up its own roles from its interface, so decide which approach your team will maintain before you create anything. Write the mapping down, because it is the document an auditor or a new administrator will ask for first.

Choose the authentication method in pg_hba.conf deliberately, because PostgreSQL documents several options, including password, LDAP, certificate and OAuth. Confirm that every password account uses SCRAM-SHA-256 and that MD5 is not left in place, since PostgreSQL 18 deprecated MD5 password authentication in favor of SCRAM. Confirm which methods your chosen version supports and whether it fits your directory service before you go live. Also confirm the exact support end dates for the version you pick. PostgreSQL 14 is supported to November 12, 2026, while PostgreSQL 18 is supported to November 14, 2030, so a version chosen now may need an upgrade plan within the next few years. Check the PostgreSQL versioning policy for the current table before you commit.

Plan backups and recovery before the first production edit. Use continuous archiving with point-in-time recovery, and test a restore to a separate server at least once, because a backup you have never restored is not yet a backup. Plan high availability separately: PostgreSQL supports hot standby servers and both synchronous and asynchronous replication, but it does not include the software to detect a failed primary and promote a standby. Automatic failover therefore needs an external tool, which you must select, configure and test. Ask your team to confirm who gets paged, how long a failover is allowed to take, and whether connection pooling with PgBouncer is needed for the number of users in the migrated system.

What drives effort and cost, and how to keep each down

The software in this migration carries no license fees, so the budget sits in people, hosting and the work of moving Access logic into PostgreSQL. Each card below names one cost component or driver, whether it is paid once or recurs, and what to ask for before signing a scope.

Internal time for the database owner

The person who knows the Access file must explain its tables, lookups, and business rules, and must test the result against real workflows. This is usually the largest internal cost and it is one-time for the migration, then recurring as a small share of time for ownership. Ask the implementation partner to state which owner hours are assumed and who signs off each table. Check whether anyone else in the team can answer questions about the old database.

Number of tables and relationships

Each table, foreign key and lookup needs a schema decision: data types, primary keys, and whether a relationship becomes a constraint or a view. A database with many interlinked tables costs more to design and test than a flat one, even if the row count is small. Ask for a table inventory with relationship counts in the quote, since this is the main input to the schema design estimate.

Amount of VBA and query logic

Access queries can usually be rebuilt as PostgreSQL views, but VBA procedures, event handlers and custom forms need to be rewritten as application code, triggers or stored logic. The more VBA the Access file contains, the more the scope grows beyond data movement. Ask the partner to classify each procedure as a view, a trigger, a rewrite or a retirement before agreeing a fixed scope.

Attachment volume and file handling

Access stores attachments and OLE objects in ways that the standard export does not carry across cleanly, so files must be extracted and linked again. Total file volume drives storage size, backup duration and copy time during cutover. Ask for a count and total size of attachments per table, and confirm how files will be referenced from the new database.

Number of roles and access rules

Mathesar uses PostgreSQL roles and privileges for access control, so each group of users needs a role with specific grants on schemas and tables. Role design is a one-time task, but every new team or permission change becomes a recurring administration task. Ask for the list of user groups, the permissions each needs, and who approves changes after go-live.

Hosting, backup and recurring upgrades

PostgreSQL and Mathesar run on a server you control, so hosting, backup tooling, monitoring and patching are the recurring costs. PostgreSQL 14 is supported until November 12, 2026, so a major upgrade may fall within the first year of operation, and minor releases arrive at least every three months. Ask the quote to separate hosting, backup, patching and the planned major upgrade, and to name who performs each one.

What usually goes wrong in an Access to PostgreSQL move

Why do Access Date/Time and Yes/No fields break after a PostgreSQL import?

Access stores Date/Time values without a clear time zone and represents Yes/No as -1 and 0 in exports, so a naive import can produce text columns or shifted timestamps. Map each field deliberately before loading: use date where only the day matters, timestamp with time zone where the moment matters, and boolean for Yes/No. Convert the exported values in a staging step and check row counts and sample dates against the Access source. Confirm the exact export format with a test table in your own environment before running the full move.

How do you stop attachments from being lost during an Access export?

Attachment and OLE fields do not come across in a CSV export, so the files are left behind unless you handle them separately. Inventory every attachment field before starting, extract the files with a separate process, and store them in a known location such as object storage or a file share. Then keep a column in PostgreSQL that holds the file path or identifier, and check a sample of records end to end. Mathesar's file data type is a useful target, but confirm how it stores and serves files in your version before relying on it.

Why do lookup fields arrive as numbers, and how do you fix them?

Access lookup fields are exported as the ID of the related record, not the readable value, so a customer name arrives as a number that means nothing in PostgreSQL. Map each lookup to a foreign key on the related table, load the parent tables first, and resolve the IDs to the new keys. Keep the original Access IDs in a separate column during the transition so you can trace any row back to its source. Test joins against a sample of known records before cutover.

What happens to multivalued fields when Access flattens them?

Multivalued fields are flattened into a single delimited text value on export, which loses the one-to-many structure and makes the data hard to filter or join. Replace each multivalued field with a junction table that holds one row per value, with foreign keys to both sides. Write the split as a scripted step so it can be rerun, and count the total values before and after to confirm nothing was dropped. Ask whoever owns the data which of these fields need real relationships and which were only used as tags.

How do you prevent users from editing data during the parallel run?

If people keep editing Access while PostgreSQL is being tested, the two copies diverge and the final load overwrites or misses changes. Set a freeze date, make the Access file read-only for the migrated tables, and tell users where edits go from that point. Plan a delta load for the last changes before cutover, and compare row counts and checksums for each table. Confirm the freeze window and rollback steps in writing with the business owners before the parallel run begins.

Why are PostgreSQL roles often set too broadly, and how do you scope them?

Teams often give every user the owner role or a shared login because it is faster during setup, and that leaves the database with no meaningful access control. Mathesar bases its access control on PostgreSQL roles and privileges, so the role design determines who can read, insert, update or delete. Create group roles for each function, grant only the table and schema privileges they need, and avoid the owner role for daily use. Review the grants with the security team, and test each role with a non-admin account before go-live.

Which Mathesar features can you assume will work, and which do you need to test?

Mathesar connects to an existing PostgreSQL database, provides a spreadsheet-like interface, imports CSV with several delimiters, and offers a form builder and a Data Explorer. Do not assume that every Access form, report, macro or VBA routine has an equivalent, because the logic often needs to move into views, database functions or an application layer. List every Access object the business uses, mark which ones Mathesar covers, and test the gaps with real users. Confirm the current feature set against the project documentation for the version you deploy.

What does Mathesar's beta status mean for a production database?

Mathesar describes itself as in public beta, so interfaces and behavior may still change between releases. Pin a specific version, test upgrades in a staging copy, and keep a tested backup of the PostgreSQL database before each change. Check the release notes for each version you consider, and confirm the PostgreSQL and Python versions it supports before choosing the database version. Decide in advance whether the business can accept beta-stage support, or whether a longer validation period is needed.

When PostgreSQL with Mathesar fits better than Baserow or Grist

Choose PostgreSQL with Mathesar when the Access database is really a relational data model that people query and maintain, and when the team wants the access rules to live in the database itself. Baserow and Grist are strongest when the main job is an application: a no-code interface with forms, views and automations built around a set of tables. PostgreSQL gives you explicit primary and foreign keys, constraints, typed columns and views that any SQL client can read, which matters when several downstream reports or integrations depend on the same tables.

The fit is also about people. If your team already writes SQL, manages PostgreSQL backups, or has a DBA or platform engineer who will own the server, the database becomes something they can inspect, script and version directly. Mathesar then sits on top as the everyday editing surface, with spreadsheet-like tables, forms and the Data Explorer, while access follows PostgreSQL roles and privileges. Before committing, confirm which Mathesar features your release supports, since the project describes itself as in public beta, and check the current Mathesar version support table against the PostgreSQL version you plan to run.

A calculation-heavy Access file, where most of the value sits in formulas that recalculate across a sheet, is usually a poorer match for this stack, and Grist may suit it better. For the wider choice between Access as a front end and a server database, read the sibling comparison pages for Microsoft Access vs PostgreSQL with Mathesar and the Baserow and Grist comparisons. Whichever option you pick, write down who owns schema changes and who grants roles before the migration starts.

Migrating Access to PostgreSQL: questions buyers ask before hiring help

What drives the cost of migrating Access to PostgreSQL?

The cost depends mainly on how much logic sits inside Access, not on the row count alone. Costs come from three parts: the internal time to export and check data, the engineering work to map types, keys and queries into PostgreSQL views and roles, and the setup of Mathesar and the server. Simple tables with few forms and no VBA cost far less than a database with dozens of queries, custom modules and reports that must be rebuilt. Server hosting and backups recur every year, while the migration itself is one-time. Ask any provider for a written scope that lists tables, queries, forms, reports, VBA modules and users, and for the assumptions behind each line. Access licenses you no longer need are a saving you should count separately.

How long does an Access to PostgreSQL migration take?

Duration is set by the number of tables, the complexity of queries and VBA, the data quality, and how many users must be trained and tested. A database with a small set of clean tables moves much faster than one with years of undocumented macros and lookup fields. Ask for a timeline tied to phases: inventory, data export and type mapping, load and validation in PostgreSQL, rebuilding queries as views, role design, Mathesar setup, user acceptance testing and cutover. Confirm how many test rounds are included and who signs off each phase. Do not accept a duration that is not linked to a written scope.

What must our internal team provide for the migration?

Your team must supply the knowledge the database itself does not record. Expect to provide: a named business owner who can decide on data rules, access to the current .accdb file and a copy for testing, a list of who uses each form and report, and the people who can confirm whether a result is correct. Someone from IT should provide a PostgreSQL server or cloud account, network access, backup storage and identity arrangements. Agree these responsibilities in writing before the work starts, because delays in sign-off are a common cause of schedule slips.

Can our own staff migrate Access to PostgreSQL without outside help?

Yes, a capable team can do it, but the work is more than copying tables. Staff need working knowledge of PostgreSQL data types, primary and foreign keys, roles and privileges, and backup and restore, plus enough Access knowledge to read existing queries and VBA. The official PostgreSQL documentation covers the database side in detail, and Mathesar's documentation covers its interface and CSV import. The main risks for a first-time team are silent data changes during type mapping, missed business rules hidden in VBA, and access rules set too broadly. If the team has no one who has run a PostgreSQL server in production, a fixed-scope engagement with written deliverables reduces that risk.

What happens to VBA, queries and reports during the move?

VBA modules, macros and reports do not move as they are. Tables move to PostgreSQL tables, and simple select queries typically become views. Logic that changes data or drives a user interface must be rewritten, for example as application code, database functions or triggers, depending on where you want it to run. Reports need a new home, such as a BI tool or Mathesar's Data Explorer for queries and tables. Before you start, list every VBA procedure and macro, mark which are still in use and which can be retired, and agree which business rules must be preserved. Your provider should show how each item is mapped and tested.

Is Mathesar ready for production use?

Mathesar describes itself as in public beta, and its latest tagged releases in the supplied sources are 0.12.0 on July 2, 2026 and 0.11.0 on May 28, 2026. It is open source under the GPLv3 license and is maintained by a 501(c)(3) nonprofit that states it is committed to remaining self-hostable. Before relying on it for line-of-business work, check the version support table for the PostgreSQL and Python versions you plan to run, test the forms, Data Explorer and file data type with your own data, and confirm how the project handles security fixes and upgrades. Because Mathesar works on top of PostgreSQL, the data itself stays in a standard, widely supported database even if you later change the front end.

How do PostgreSQL roles replace Access user permissions?

Access permissions are usually set per file or per shared network folder, which gives coarse control. PostgreSQL roles and privileges let you grant access per schema, table, view and column, and Mathesar bases its access control on those roles. Plan the role model before importing data: group users by job function, give read-only roles to reporting users, and avoid giving application users ownership of tables. Confirm how your identity provider will connect to PostgreSQL, since PostgreSQL documents several authentication methods, including password, LDAP, certificate and OAuth, and you should choose one that matches your directory. Test each role with a real user account before cutover.

What should we check about backups and PostgreSQL versions before go-live?

Confirm the PostgreSQL major version you install and its support end date. The PostgreSQL versioning policy lists 14 as supported until November 12, 2026, and 15, 16, 17 and 18 with later end dates, so choosing a version that will stay supported for the life of the system matters. Set up regular backups and test a restore before the cutover, and document the recovery point and recovery time you expect. PostgreSQL does not detect a failed primary and fail over by itself, so if you need automatic failover, budget for external tooling and its operation. Ask your provider how upgrades will be scheduled, including minor releases and major upgrades using logical replication or pg_upgrade.

How DeployOpen scopes and runs the Access to PostgreSQL move

DeployOpen plans and implements self-hosted open-source platforms inside the client's own infrastructure, including the move from an Access database to PostgreSQL with Mathesar. Each engagement starts with a written scope that fixes what is moved, what is rebuilt and what is handed over.

How we scope

  • Inventory every Access table, query, form, report and macro, and mark which ones carry business rules.
  • Agree in writing which tables, attachments and linked files move, and which are archived or retired.
  • Map each Access data type and key to PostgreSQL types, primary keys and foreign keys before any data is copied.

How we build

  • Provision PostgreSQL and Mathesar in the client's own cloud account, data center or air-gapped network.
  • Rebuild Access queries as PostgreSQL views and set roles and privileges that match the agreed access rules.
  • Test imports on copies of the data, checking row counts, keys, dates and attachment links before cutover.

How we hand over

  • Document the schema, role model, import steps, backup and restore procedure and the cutover runbook.
  • Train the named client staff who will edit data in Mathesar, build forms and run the Data Explorer.
  • Deliver a signed-off test record and a retained copy of the original Access files for the agreed period.

How we support

  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.
  • Ongoing support, upgrades and PostgreSQL minor-version patching are available as a retainer.
  • Confirm with us the support window, escalation path and who approves changes to roles and schema after handover.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.