Access database migration to SQL Server, PostgreSQL, and modern platforms — from a Zeeland, MI company that has migrated hundreds of Access databases since 2004. We extract your tables, queries, forms, reports, VBA modules, and linked table chains into production-grade systems that handle 10,000+ concurrent users instead of 10.
Microsoft Access has a hard 2GB file size limit. Not a recommendation. Not a best practice guideline. A hard ceiling baked into the Jet and ACE database engines that Microsoft has never raised since Access 97. When your MDB or ACCDB file hits 2GB, Access does not slow down gracefully or warn you with a friendly dialog box. It corrupts. Tables become unreadable. Queries return garbage. Compact and Repair — the tool every Access developer knows by heart — fails because the file is structurally damaged beyond recovery. If you do not have a backup from before the corruption event, your data is gone. We have received calls from companies that lost months of operational data because a single Access database grew past the 2GB threshold on a Friday afternoon and nobody noticed until Monday morning.
The 2GB limit is the catastrophic failure mode, but Access databases start degrading long before they hit that wall. Performance drops noticeably around 500MB–1GB. Queries that used to return in under a second take 10–15 seconds. Forms take 5–8 seconds to load. Report generation that used to complete during a coffee break now runs for 45 minutes. The Jet/ACE engine was designed for single-user desktop databases in the mid-1990s. It has no query optimizer worth mentioning, no execution plan caching, no parallel query execution, and no ability to use more than a fraction of available system memory. Every query performs a full table scan unless you have manually created indexes, and even indexed queries degrade as fragmentation increases because the engine has no background maintenance processes.
Multi-user Access is where the real horror stories live. Microsoft's documentation says Access supports up to 255 concurrent connections. In practice, anything above 5–10 simultaneous users causes record locking conflicts, database corruption, and split-database architectures that create their own maintenance nightmares. The standard workaround — splitting the database into a backend MDB on a network share and frontend MDB copies on each workstation — introduces a new failure mode: linked tables break when the network path changes, when the file server is rebooted, when someone maps a drive letter differently, or when Windows updates the SMB protocol version. Every Access developer has spent hours troubleshooting 'Could not find file' and 'Record is locked by user ADMIN on machine' errors that bring entire departments to a standstill.
Access has no real security model. The legacy MDW workgroup security file was deprecated in Access 2007 and was trivially bypassable even when it worked. Any user with file-system access to the MDB can open it directly, bypass your login form entirely, and view or modify any table. There is no row-level security, no column-level security, no audit trail, no encryption at rest in any meaningful sense, and no way to prevent a user from simply copying the entire database file to a USB drive. For companies in regulated industries — healthcare, finance, insurance, manufacturing with ITAR requirements — running business data in Access is a compliance violation waiting to be discovered during an audit.
Then there is the VBA problem. Most Access databases that have been in production for more than a few years have accumulated thousands of lines of VBA code behind forms, reports, and modules. This code typically has no version control, no documentation, no error handling, and dependencies on specific Windows registry settings, ODBC DSNs, or COM libraries that may or may not be installed on any given workstation. The developer who wrote the original code left the company in 2011. The person who modified it in 2017 no longer remembers what they changed. Nobody understands the full dependency chain. The business runs on code that nobody can confidently modify, and every Windows update or Office patch is a dice roll on whether something critical will break.
Hard 2GB file size limit causes catastrophic, unrecoverable corruption — not gradual degradation, total data loss
Performance collapse at 500MB–1GB: 10–15 second query times, 45-minute report generation, unusable form load speeds
Multi-user limit of 5–10 practical concurrent users despite Microsoft's claim of 255 — record locking, split DB corruption, linked table failures
Zero meaningful security: no row-level access control, no encryption at rest, no audit trail, trivially bypassable workgroup security
VBA spaghetti code with no version control, no documentation, and dependencies on departed employees' knowledge
Linked tables break on network path changes, drive letter remapping, SMB protocol updates, and file server reboots
Compact and Repair fails on corrupted files above 1.5–2GB, leaving no recovery path without external backup
Compliance risk in regulated industries — HIPAA, SOX, ITAR, PCI-DSS all violated by Access's lack of access controls and audit logging
Our engineers have built this exact solution for other businesses. Let's discuss your requirements.
Migrating from Access to SQL Server is not an upgrade. It is a fundamental architecture change from a file-based desktop database engine to a client-server relational database management system. SQL Server handles databases up to 524 petabytes. It supports tens of thousands of concurrent connections with row-level locking instead of page-level locking. It has a real query optimizer that generates and caches execution plans, parallel query processing across multiple CPU cores, automatic index maintenance, and an entire security infrastructure with role-based access, row-level security, column-level encryption, Transparent Data Encryption at rest, and comprehensive audit logging that satisfies HIPAA, SOX, PCI-DSS, and ITAR requirements out of the box.
FreedomDev has been migrating Access databases to SQL Server, PostgreSQL, and web-based platforms since 2004. We handle the full migration scope: table structures and data types (Access data types do not map 1:1 to SQL Server — Memo fields, OLE Object fields, Yes/No fields, Hyperlink fields, and Attachment fields all require specific conversion strategies), query translation (Access SQL is a dialect with non-standard syntax that SQL Server will not accept as-is), VBA business logic extraction and reimplementation in stored procedures or application code, form and report replacement with modern web interfaces, linked table dependency resolution, and ODBC/connection reconfiguration for phased migration where some components stay in Access temporarily while others move to SQL Server.
The migration approach depends on your Access database complexity and your tolerance for downtime. For simple databases — under 50 tables, minimal VBA, no complex subforms — we can use SQL Server Migration Assistant (SSMA) as a starting point and then manually fix the data type mappings, query translations, and relationship constraints that SSMA gets wrong (it always gets some wrong). For complex databases — hundreds of tables, extensive VBA codebases, deeply nested subforms, linked table chains across multiple backend files, or Access Data Projects — we build a custom migration plan that phases the transition over weeks or months so your team can continue working while the migration happens in parallel. Nobody flips a switch on Friday and shows up Monday hoping the new system works. That is how migrations fail.
Access and SQL Server data types are not interchangeable. Access Memo fields become NVARCHAR(MAX) or NTEXT. Yes/No becomes BIT. AutoNumber becomes INT IDENTITY or BIGINT IDENTITY depending on row count trajectory. OLE Object fields containing embedded Excel spreadsheets, Word documents, or images require extraction and external storage. Attachment fields — a multi-valued column type unique to Access — have no SQL Server equivalent and must be decomposed into a related table with individual file records. Currency fields map to MONEY or DECIMAL(19,4) depending on whether you need exact decimal arithmetic. We audit every column, map every data type, validate conversion accuracy row-by-row, and handle the edge cases that automated tools miss.
Access uses a non-standard SQL dialect that SQL Server rejects. IIF() becomes CASE WHEN. Nz() becomes ISNULL() or COALESCE(). Access crosstab queries (TRANSFORM/PIVOT) require complete rewriting as T-SQL PIVOT operations with different syntax. Parameterized queries that reference form controls — the standard Access pattern of [Forms]![frmMain]![txtCustomerID] — need to become stored procedure parameters or application-layer parameterized queries. Access-specific date functions (DateSerial, DatePart, DateAdd with Access-specific interval codes) all require T-SQL equivalents. We translate every query, validate output equivalence against the original Access results, and optimize execution plans for SQL Server's query engine.
The VBA code in your Access database is almost certainly doing more than you think. Form-level validation rules, complex calculated fields, business logic buried in On_Click events, report formatting logic, import/export routines, email generation, and integration with other Office applications through COM automation. We reverse-engineer every VBA module, document the business rules it implements, and re-implement that logic in the appropriate tier: data validation moves to SQL Server constraints and triggers, business calculations become stored procedures or application-layer code, UI logic moves to the new front-end framework, and integrations become API calls or scheduled jobs. Nothing gets lost. Nothing gets silently dropped because an automated tool did not understand what a VBA subroutine was doing.
Access forms and reports do not migrate to SQL Server because SQL Server is a database engine, not an application platform. Your forms need a new front end: a web application, a desktop application (.NET WinForms/WPF), or a hybrid. For companies replacing Access forms, we typically build web interfaces using React or Next.js with a .NET or Node.js API layer connecting to SQL Server. Reports migrate to SQL Server Reporting Services (SSRS), Power BI, or custom web-based reporting depending on distribution requirements. We rebuild every form and every report with the same fields, the same layout logic, and the same workflow — your users should recognize the new system on day one.
Most production Access databases are not a single file. They are a front-end ACCDB linked to one or more back-end MDBs, possibly with ODBC links to SQL Server tables, Excel spreadsheet links, SharePoint list links, and text file links all in the same database. Each linked table is a dependency that must be traced, tested, and either migrated or reconnected. We map the full dependency graph — every linked table, every connection string, every DSN reference — and build a migration plan that accounts for the entire chain. Partial migrations where some tables move to SQL Server while others stay in Access temporarily require linked table reconfiguration and careful testing of cross-engine queries.
Big-bang migrations fail. We migrate Access databases in phases: backend tables first (re-link Access frontend to SQL Server via ODBC so users keep their familiar forms while the data moves), then queries and business logic, then forms and reports one module at a time. During transition, we run old and new systems in parallel with data synchronization to verify that the migrated components produce identical results. Your team continues working in the Access interface they know while we validate each phase. Cutover happens per-module, not all at once, and only after your team has tested and approved each component.
Our Access database had been running our entire quoting and order management process for 14 years. It was 1.7GB and corrupted twice in three months. FreedomDev migrated 340 tables, 1,200 queries, and 15,000 lines of VBA to SQL Server with a .NET web front end. We went from 8 users struggling with lockouts to 45 users running simultaneously without a single performance complaint.
We open every MDB and ACCDB in your environment and catalog the full scope: table count, row counts, total data volume, data types requiring special migration handling, query count and complexity, VBA module line count, form and report inventory, linked table chains with source paths, ODBC connections, external references, and macro definitions. We identify every dependency — which forms use which queries, which queries reference which tables, which VBA modules call which forms, which reports depend on which parameter queries. Deliverable: a comprehensive migration scope document with complexity rating per component, risk assessment, recommended migration sequence, and detailed cost/timeline estimate.
We design the SQL Server schema based on your Access table structures but optimized for SQL Server. This is not a direct copy. Access databases almost never have proper foreign key relationships defined (they rely on the Relationships window which is informational, not enforced by default). We normalize tables that Access developers denormalized for form convenience, add proper constraints, design indexes based on your actual query patterns, map every data type with documented conversion rules, and create the migration scripts. We review the schema with your team before any data moves.
We migrate the data in a staged process: schema creation, bulk data load, constraint application, and row-by-row validation. Access data has quirks that cause migration failures if not handled: null strings vs empty strings (Access treats them interchangeably, SQL Server does not), trailing spaces in Text fields, date values outside SQL Server's datetime range (Access stores dates from 100 AD, SQL Server datetime starts at 1753), and currency precision differences. We write validation queries that compare Access source data against SQL Server target data for every table, every column, every row. The migration is not complete until validation shows zero discrepancies.
Every Access query gets translated to T-SQL and validated for output equivalence. Make-table queries become SELECT INTO or stored procedures. Append queries become INSERT statements. Update queries and Delete queries get translated with careful attention to Access-specific join behavior (Access handles outer joins in WHERE clauses differently than SQL Server). VBA business logic gets extracted, documented, and reimplemented as stored procedures, SQL Server functions, application-layer code, or a combination depending on where the logic belongs architecturally. We test every migrated query and procedure against the original Access output.
Access forms become web or desktop application interfaces. Access reports become SSRS reports, Power BI dashboards, or web-based reports with PDF export. We rebuild the UI module by module, matching the existing workflow so your users do not need extensive retraining. Each module gets a user acceptance testing period where your team verifies that the new interface does everything the Access form did — same fields, same validations, same navigation flow, same output. We iterate based on feedback until your team signs off.
Old and new systems run simultaneously with data synchronization. Your team works in both environments, comparing results and flagging discrepancies. Once a module passes parallel validation, we cut it over and disable the Access equivalent. After all modules are cutover and the team has operated solely on the new system for a minimum of two weeks, we archive the Access databases (read-only, backed up) and decommission them. Post-migration support runs 60 days to catch any edge cases that did not surface during parallel running.
| Metric | With FreedomDev | Without |
|---|---|---|
| Maximum Database Size | 524 petabytes (SQL Server) | 2GB hard limit (Access Jet/ACE) |
| Concurrent Users | Tens of thousands with row-level locking | 5–10 practical, 255 theoretical, page-level locking |
| Query Optimization | Cost-based optimizer, execution plan caching, parallel execution | No optimizer, full table scans, single-threaded |
| Security Model | Row-level security, TDE, Always Encrypted, audit logging | Deprecated MDW files, trivially bypassable, no audit trail |
| Backup & Recovery | Point-in-time recovery, transaction logs, automated backups | Manual file copy, Compact & Repair, pray it works |
| High Availability | Always On Availability Groups, automatic failover | File on a network share — if the share goes down, everyone is locked out |
| Data Integrity | ACID transactions, enforced constraints, triggers | Corruption on network interruption, no enforced referential integrity by default |
| Maintenance | Automated index rebuilds, statistics updates, integrity checks | Manual Compact & Repair, manual re-indexing, fragmentation accumulates silently |
Schedule a direct technical consultation with our senior architects.
Make your software work for you. Let's build a sensible solution.