Sync MySQL/PostgreSQL/SQLite/MSSQL data to Google Sheets with CLI, API, and Web Dashboard
Project description
MySQL to Google Sheets Sync
A Python ETL package that synchronizes data from SQL databases to Google Sheets using Service Account authentication. Supports MySQL, PostgreSQL, SQLite, and SQL Server with four access interfaces: CLI, REST API, Web Dashboard, and Desktop Application.
Version: 1.0.0 | Python: 3.10-3.12+ | License: MIT
Features
- Multi-database support — MySQL, PostgreSQL, SQLite, SQL Server
- Multiple sync modes — full replace, append, and streaming (chunked) for large datasets
- Interactive setup wizard —
quickstartcommand walks through first-time configuration - Demo mode — try it without a real database (
--demo) - REST API (FastAPI) with OpenAPI docs at
/docs - Web Dashboard (Flask) for browser-based sync management
- Built-in scheduler — cron-based scheduling with APScheduler
- Column mapping — rename, reorder, and filter columns
- Preview & dry-run — see diffs before applying changes
- Snapshots & rollback — restore previous sheet states
- Incremental sync — timestamp-based change detection
- Job queue — async job processing with SQLite or Redis backends
- Freshness/SLA monitoring — track data staleness with alerts
- Multi-tenant — organizations, users, RBAC (owner/admin/operator/viewer)
- Notifications — email, Slack, and webhook backends
- Prometheus metrics — built-in metrics endpoint
- Subscription tiers — FREE, PRO, BUSINESS, ENTERPRISE with usage metering
- RS256 license keys — offline-validated JWT license keys
Architecture
graph TD
CLI["CLI (argparse)"] --> Core
API["REST API (FastAPI)"] --> Core
Web["Web Dashboard (Flask)"] --> Core
Desktop["Desktop (PyInstaller)"] --> Core
Core["Core ETL<br/>fetch → clean → push"] --> DB["Database<br/>MySQL · PostgreSQL<br/>SQLite · SQL Server"]
Core --> Sheets["Google Sheets<br/>(gspread)"]
Core --> Notify["Notifications<br/>Email · Slack · Webhook"]
Core -.-> Scheduler["Scheduler<br/>(APScheduler)"]
Core -.-> Jobs["Job Queue<br/>SQLite · Redis"]
Core -.-> Snapshots["Snapshots<br/>& Rollback"]
Getting Started
Try It First (No Setup Required)
pip install mysql-to-sheets
mysql-to-sheets sync --demo
This runs a sample sync with built-in demo data. See Demo Mode for details.
Full Setup
Ready to sync real data:
Step 1: Install
pip install mysql-to-sheets
Step 2: Set Up Google Cloud
- Create a service account: Google Cloud Console
- Download JSON key as
service_account.json - Enable Google Sheets API: Enable API
Step 3: Configure
mysql-to-sheets quickstart
Or create .env manually:
DB_HOST=localhost
DB_USER=readonly_user
DB_PASSWORD=secret
DB_NAME=mydb
SQL_QUERY=SELECT * FROM users LIMIT 1000
GOOGLE_SHEET_ID=your_spreadsheet_id
SERVICE_ACCOUNT_FILE=./service_account.json
Step 4: Sync
# Preview changes first
mysql-to-sheets sync --dry-run
# Run the sync
mysql-to-sheets sync
Troubleshooting
If something goes wrong:
mysql-to-sheets diagnose
Optional Dependencies
pip install mysql-to-sheets[postgres] # PostgreSQL support
pip install mysql-to-sheets[mssql] # SQL Server support
pip install mysql-to-sheets[redis] # Redis job queue backend
pip install mysql-to-sheets[desktop] # Desktop app dependencies
pip install mysql-to-sheets[all] # All optional drivers
Try Without Setup
Demo mode requires no database or Google Sheets:
mysql-to-sheets sync --demo
Development Install
git clone https://github.com/BrandonFricke/mysql-to-sheets.git
cd mysql-to-sheets
pip install -e ".[dev]"
Desktop users: Download the latest installer from GitHub Releases:
- macOS:
mysql-to-sheets-X.X.X-macos.dmg— drag to Applications- Windows:
mysql-to-sheets-X.X.X-windows-setup.exe— standard installer- Linux:
mysql-to-sheets-X.X.X-x86_64.AppImage— portable, no installation neededSee Desktop Installation for security warning bypass instructions.
Developing from source? Clone the repo, run
pip install -r requirements.txt, and usepython -m mysql_to_sheetsinstead.
Access Interfaces
CLI
python -m mysql_to_sheets sync # Run sync
python -m mysql_to_sheets sync --preview # Show diff before applying
python -m mysql_to_sheets sync --dry-run # Validate without pushing
python -m mysql_to_sheets sync --db-type=postgres # Use PostgreSQL
python -m mysql_to_sheets validate # Check configuration
python -m mysql_to_sheets diagnose # Full system diagnostics
REST API (FastAPI — port 8000)
uvicorn mysql_to_sheets.api.app:app --reload --port 8000
# Swagger docs at http://localhost:8000/docs
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/sync |
Run sync operation |
| POST | /api/v1/validate |
Validate configuration |
| GET | /api/v1/health |
Health check |
| GET | /api/v1/history |
Sync history |
| GET/POST | /api/v1/schedules |
Schedule management |
| GET | /api/v1/freshness |
SLA monitoring |
| GET | /api/v1/jobs |
Job queue status |
| GET | /metrics |
Prometheus metrics |
Web Dashboard (Flask — port 5000)
flask --app mysql_to_sheets.web.app run --port 5000
Provides a browser-based interface for sync management, schedule configuration, job monitoring, snapshot/rollback, and diagnostics.
Monitoring (Prometheus + Grafana)
# Start API with Prometheus and Grafana
docker compose --profile monitoring up
# Prometheus: http://localhost:9090
# Grafana: http://localhost:3000 (admin/admin)
Pre-configured with auto-provisioned datasource, alert rules, and dashboard.
Supported Databases
| Database | DB_TYPE |
Default Port | Driver |
|---|---|---|---|
| MySQL | mysql |
3306 | mysql-connector-python |
| PostgreSQL | postgres |
5432 | psycopg2-binary |
| SQLite | sqlite |
— | built-in |
| SQL Server | mssql |
1433 | pymssql |
# Examples
python -m mysql_to_sheets sync --db-type=mysql # default
python -m mysql_to_sheets sync --db-type=postgres
python -m mysql_to_sheets sync --db-type=sqlite
python -m mysql_to_sheets sync --db-type=mssql
You can also use a DATABASE_URL connection URI instead of individual variables:
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
Configuration
Copy .env.example to .env and set the required variables:
| Variable | Required | Description |
|---|---|---|
DB_USER |
Yes | Database username |
DB_PASSWORD |
Yes | Database password |
DB_NAME |
Yes | Database name (or file path for SQLite) |
GOOGLE_SHEET_ID |
Yes | Target spreadsheet ID or full URL |
SQL_QUERY |
Yes | SQL query to execute |
Optional variables cover database host/port, SSL, connection pooling, worksheet management, notifications, scheduling, and more. See .env.example for the full list.
Sync Modes
| Mode | Flag | Description |
|---|---|---|
| Replace | (default) | Clear sheet, push all data — best for full refresh |
| Append | --mode=append |
Add rows without clearing — for incremental additions |
| Streaming | --mode=streaming --chunk-size=500 |
Process in chunks — for large datasets (>10k rows) |
Additional options:
python -m mysql_to_sheets sync --preview # Show diff before applying
python -m mysql_to_sheets sync --incremental # Only sync changed rows
python -m mysql_to_sheets sync --create-worksheet # Auto-create missing tab
python -m mysql_to_sheets sync --column-case=title # Transform column names
Common Commands
# Sync
python -m mysql_to_sheets sync
python -m mysql_to_sheets sync --demo
python -m mysql_to_sheets sync --dry-run
python -m mysql_to_sheets sync --preview --output=json
# Setup & diagnostics
python -m mysql_to_sheets quickstart
python -m mysql_to_sheets validate
python -m mysql_to_sheets test-db --diagnose
python -m mysql_to_sheets test-sheets --diagnose
python -m mysql_to_sheets diagnose
# Worksheets
mysql-to-sheets sheet list
mysql-to-sheets sheet create --name="Data Export"
# Scheduling
mysql-to-sheets schedule add --name="daily" --cron="0 6 * * *"
mysql-to-sheets schedule list
mysql-to-sheets schedule run
# Snapshots
python -m mysql_to_sheets snapshot create --name="Before update"
python -m mysql_to_sheets rollback --snapshot-id=1
# Database migrations
mysql-to-sheets db upgrade
Project Structure
mysql-to-sheets/
├── mysql_to_sheets/ # Main package
│ ├── core/ # Business logic (40+ modules)
│ │ ├── config.py # Config dataclass with singleton
│ │ ├── sync.py # SyncService + ETL functions
│ │ ├── exceptions.py # Error hierarchy with codes
│ │ ├── database/ # MySQL/PostgreSQL/SQLite/MSSQL
│ │ ├── notifications/ # Email, Slack, webhook
│ │ ├── scheduler/ # APScheduler integration
│ │ └── webhooks/ # Webhook delivery
│ ├── cli/ # Command-line interface (25 commands)
│ ├── api/ # FastAPI REST API
│ │ ├── app.py # Application factory
│ │ ├── routes.py # Main router
│ │ └── middleware/ # Auth, rate limiting, CORS, RBAC
│ ├── web/ # Flask web dashboard
│ │ ├── app.py # Application factory
│ │ ├── blueprints/ # Route handlers (12 blueprints)
│ │ └── templates/ # Jinja2 templates (23 templates)
│ ├── models/ # SQLAlchemy models (17 models)
│ └── desktop/ # PyInstaller desktop app
├── tests/ # Test suite (57 test files)
├── alembic/ # Database migrations
├── helm/ # Kubernetes Helm chart
├── monitoring/ # Prometheus alerts + Grafana dashboards
├── .env.example # Configuration template
├── requirements.txt # Python dependencies
└── pyproject.toml # Package config (ruff, mypy, pytest)
Development
# Install dependencies
pip install -r requirements.txt
# Run tests
pytest
pytest --cov=mysql_to_sheets
# Lint
ruff check mysql_to_sheets
# Type check
mypy mysql_to_sheets
Desktop Installation
Download the installer for your platform from GitHub Releases.
macOS
- Download
mysql-to-sheets-X.X.X-macos.dmg - Open the DMG and drag "MySQL to Sheets Sync" to Applications
- On first launch, you may see a security warning (app is not notarized)
Bypassing macOS Gatekeeper:
- Right-click (or Ctrl+click) the app in Applications
- Select "Open" from the context menu
- Click "Open" in the dialog
- The app will launch and be remembered for future launches
Windows
- Download
mysql-to-sheets-X.X.X-windows-setup.exe - Run the installer — it will create Start Menu shortcuts
- On first launch, you may see a SmartScreen warning (app is not code-signed)
Bypassing Windows SmartScreen:
- Click "More info" on the warning dialog
- Click "Run anyway"
- The app will launch normally after this
Linux
- Download
mysql-to-sheets-X.X.X-x86_64.AppImage - Make it executable:
chmod +x mysql-to-sheets-*.AppImage - Run it:
./mysql-to-sheets-*.AppImage
No installation needed — AppImage is a portable format.
Auto-Updates
The desktop app checks for updates automatically once per day. You can also check manually via the system tray menu: Check for Updates...
When an update is available, you'll see a notification and a menu item to download it.
Google Cloud Setup
- Create a project in Google Cloud Console
- Enable the Google Sheets API (APIs & Services > Library)
- Create a Service Account (APIs & Services > Credentials > Create Credentials)
- Download the JSON key and save as
service_account.json - Find the
client_emailin the JSON file - Share your Google Sheet with that email as Editor
For detailed instructions, common mistakes, and troubleshooting, see the Google Cloud Setup Guide.
Security Notes
- Never commit
.envorservice_account.jsonto version control (already in.gitignore) - Create a database user with SELECT-only permissions for sync operations
- SQL validation is enabled by default (blocks DROP, DELETE, etc.)
- API authentication is enabled by default
- Account lockout after 5 failed login attempts
- RBAC uses fail-closed design — unknown permissions are denied
- Webhook deliveries are signed with HMAC-SHA256
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
| "Spreadsheet not found" | Sheet ID incorrect or not shared | Verify ID and share with service account email |
| "Connection refused" | Database not accessible | Check host, port, firewall rules |
| "Service account file not found" | Missing credentials | Download JSON from Google Cloud Console |
| "Worksheet not found" | Tab name mismatch | Check GOOGLE_WORKSHEET_NAME |
| "UnsupportedDatabaseError" | Invalid DB_TYPE |
Use mysql, postgres, sqlite, or mssql |
| "ModuleNotFoundError: psycopg2" | PostgreSQL driver missing | pip install mysql-to-sheets[postgres] |
Run full diagnostics:
python -m mysql_to_sheets diagnose
Roadmap
- PRIORITIES.md — Market-readiness priorities (ship blockers → growth)
- ROADMAP.md — Completed development phases and future items
- STANDALONE_PROJECTS.md — Extractable packages and standalone services
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mysql_to_sheets-1.0.0.tar.gz.
File metadata
- Download URL: mysql_to_sheets-1.0.0.tar.gz
- Upload date:
- Size: 1.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b545ac282254baa3f00e4bee0cb4e99ff13510a6e7eb99beeb3b54099c5190a9
|
|
| MD5 |
5309d1cdedd6b2ada76a25fd8e55ce43
|
|
| BLAKE2b-256 |
dac86234b1905c7b6ebfe82b7fa4f61fd086da2e9ec9e5847a6348f64a78156a
|
Provenance
The following attestation bundles were made for mysql_to_sheets-1.0.0.tar.gz:
Publisher:
pypi-publish.yml on BrandonFricke/mysql-to-sheets
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mysql_to_sheets-1.0.0.tar.gz -
Subject digest:
b545ac282254baa3f00e4bee0cb4e99ff13510a6e7eb99beeb3b54099c5190a9 - Sigstore transparency entry: 879635176
- Sigstore integration time:
-
Permalink:
BrandonFricke/mysql-to-sheets@583b6f705c2bd851883e8ab960cfb85d8e90106e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/BrandonFricke
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@583b6f705c2bd851883e8ab960cfb85d8e90106e -
Trigger Event:
push
-
Statement type:
File details
Details for the file mysql_to_sheets-1.0.0-py3-none-any.whl.
File metadata
- Download URL: mysql_to_sheets-1.0.0-py3-none-any.whl
- Upload date:
- Size: 972.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81c63e2167a1a5e637e3d201547edaecb289a7ab462b82605d3361da09a7b0a4
|
|
| MD5 |
ed6464b32ffb81a26eb3e4c936212ed3
|
|
| BLAKE2b-256 |
00b8dcb716eac51f76e3063ab290dad51b85d6af3115faba08e477aa52d7abcb
|
Provenance
The following attestation bundles were made for mysql_to_sheets-1.0.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on BrandonFricke/mysql-to-sheets
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mysql_to_sheets-1.0.0-py3-none-any.whl -
Subject digest:
81c63e2167a1a5e637e3d201547edaecb289a7ab462b82605d3361da09a7b0a4 - Sigstore transparency entry: 879635255
- Sigstore integration time:
-
Permalink:
BrandonFricke/mysql-to-sheets@583b6f705c2bd851883e8ab960cfb85d8e90106e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/BrandonFricke
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@583b6f705c2bd851883e8ab960cfb85d8e90106e -
Trigger Event:
push
-
Statement type: