Most mornings at work I had three database tools open. DataGrip for MySQL, a Redshift-compatible client, and the AWS console for DynamoDB. That is three windows, three sets
of saved credentials, three different query histories, and about 1.5GB of RAM just to look at tables.
I built https://shubhesh07.github.io/db-connect/ to replace all three. It is a free desktop database IDE for MySQL, Amazon Redshift, and DynamoDB. The installed binary is
18MB. It opens in under two seconds. And it does not bundle Chromium.
This post covers the technical decisions behind it — what worked, what was painful, and what I would change.
The problem
If you work at a company that runs MySQL for transactional data, Redshift for analytics, and DynamoDB for high-throughput key-value access, you know the tool fragmentation
problem. Every database client either:
- Supports relational databases well but ignores DynamoDB entirely
- Is built on Java and takes 15 seconds to show you a cursor
- Costs $25/month per seat for features you use 10% of
I wanted one tool that could connect to all three, store credentials securely, and not make my laptop fan spin up just by existing in the dock.
Why not just use what exists
I tried everything. Here is an honest comparison:
┌────────────┬──────────────────┬──────────────┬─────────┬───────────────┬──────────┐
│ Tool │ Price │ Install Size │ Startup │ Stack │ DynamoDB │
├────────────┼──────────────────┼──────────────┼─────────┼───────────────┼──────────┤
│ DataGrip │ $25/mo │ ~800MB │ 10-30s │ Java/IntelliJ │ No │
├────────────┼──────────────────┼──────────────┼─────────┼───────────────┼──────────┤
│ DBeaver │ Free (community) │ ~400MB │ 5-15s │ Java/Eclipse │ No │
├────────────┼──────────────────┼──────────────┼─────────┼───────────────┼──────────┤
│ TablePlus │ $89 (license) │ ~80MB │ <3s │ Native │ Yes │
├────────────┼──────────────────┼──────────────┼─────────┼───────────────┼──────────┤
│ DB Connect │ Free │ 18MB │ <2s │ Go + Wails │ Yes │
└────────────┴──────────────────┴──────────────┴─────────┴───────────────┴──────────┘
DataGrip is genuinely excellent if you live in relational-only land and your company pays for JetBrains. But no DynamoDB, and the cold start time on a Monday morning is
painful.
DBeaver is the community workhorse. It does a lot. It also runs on Eclipse, which means it does a lot slowly. No DynamoDB support in the free tier.
TablePlus is the closest to what I wanted — it is native, fast, and supports DynamoDB. But the DynamoDB experience is basic, it is not free, and I wanted features like
EXPLAIN visualization and parameterized saved queries that it does not offer.
None of them solved my specific problem: a fast, lightweight, free tool that treats MySQL, Redshift, and DynamoDB as equal citizens.
The tech stack decision
The first question was Electron vs. something else. Electron is the safe choice — massive ecosystem, battle-tested, every tutorial on the internet. But Electron means
bundling Chromium, which means:
- 400MB+ installed size minimum
- 150-300MB RAM just for the shell before your app does anything
- A full browser process even though you are building a desktop app
I went with https://wails.io instead. Wails uses the system's native WebView (WebKit on macOS, WebView2 on Windows) and a Go backend. The tradeoff is real: you lose some
cross-browser consistency and the Chrome DevTools you are used to. But you gain a single compiled binary, native performance, and an 18MB install.
Go was a natural fit for the backend. Database drivers are mature in the Go ecosystem (database/sql, go-sql-driver/mysql, aws-sdk-go-v2). Goroutines make it trivial to run
queries without blocking the UI — every query execution spawns a goroutine, and the frontend gets results via Wails' binding system. No thread pools to manage, no callback
hell.
The frontend is React 18 with TypeScript. Nothing exotic. The interesting piece is Monaco — the same editor engine that powers VS Code — which gives you autocomplete, syntax
highlighting, multi-cursor editing, and bracket matching without building any of that from scratch.
Architecture overview
┌────────────────────��────────────┐
│ React + TypeScript + Monaco │ ← UI layer
│ (runs in system WebView) │
��─────────────────────────────────┤
│ Wails v2 bridge │ ← function bindings, events
├────��─────────────────���──────────┤
│ Go backend │
│ ├── Connection manager │ ← pool management, SSH tunnels
│ ├── Query executor │ ← goroutine per query
│ ├── Credential store │ ← AES-256-GCM + OS keychain
│ ├─�� DynamoDB client ��� ← scan/query/GetItem abstraction
│ │
└─────────────────────────────────┘
Wails generates TypeScript bindings from Go structs and methods automatically. You export a Go method, and it becomes callable from JavaScript. No REST API, no WebSocket
protocol, no serialization layer to maintain. The Go backend owns all database connections, all encryption, and all credential storage. The frontend never touches raw
connection strings or passwords.
One quirk worth mentioning: PostHog analytics are routed through the Go backend as a proxy. Wails' WebView does not let you make arbitrary cross-origin requests the way a
normal browser tab would, so the Go layer handles the HTTP calls to PostHog's ingest endpoint. It is a small thing, but the kind of thing you do not discover until you are
debugging why your analytics silently fail.
The DynamoDB challenge
Most database tools ignore DynamoDB because it does not speak SQL and its data model is genuinely different. You cannot just bolt a SQL editor onto it.
DynamoDB has partition keys, sort keys, global secondary indexes, and a type system that includes String (S), Number (N), Binary (B), List (L), Map (M), String Set (SS),
Number Set (NS), and Binary Set (BS). Building a query means specifying key conditions, optional filter expressions, selecting an index, and understanding the difference
between a Query (which requires a partition key) and a Scan (which reads the entire table and should terrify you in production).
DB Connect has a visual query builder that handles all of this. You pick your table, choose Query or Scan or GetItem, select a GSI if needed, build filter expressions with a
form-based UI, and see results with proper type annotations.
The type system was the hardest part. A single DynamoDB item can have nested Maps containing Lists containing Maps containing Number Sets. The frontend needs to render this
recursively, and the Go backend needs to marshal and unmarshal it correctly through the AWS SDK. I spent more time on DynamoDB type handling than on the entire MySQL
integration.
Security decisions
Credentials are encrypted with AES-256-GCM before being stored. The encryption key lives in the OS keychain — macOS Keychain on Mac, Windows Credential Manager on Windows.
Your database passwords never exist as plaintext on disk.
This matters more than people think. I have seen popular database tools that store passwords in plaintext JSON files or use reversible encoding that any script can decode. If
someone gets read access to your home directory — through a compromised dependency, a shared machine, or a backup that was not encrypted — they get every database credential
you have saved.
SSH tunnel support is built in for MySQL connections. You configure the tunnel parameters alongside your connection details, and the Go backend establishes the tunnel before
connecting to MySQL through it.
Performance tricks
Three things keep DB Connect fast with large data:
Virtual scrolling. Result sets render using virtualized rows. Only the visible rows plus a small buffer exist in the DOM at any time. You can scroll through hundreds of
thousands of rows without the browser choking on DOM nodes.
Goroutine-per-query. Every query execution runs in its own goroutine. The Wails event system pushes results back to the frontend when they are ready. Long-running Redshift
analytics queries do not freeze the UI — you can switch tabs and run a quick MySQL lookup while waiting.
Binary size optimization. Go 1.25 with Wails produces a single binary. No JVM, no Node runtime, no native module compilation. The universal macOS build (Intel + Apple Silicon
in one binary) is still under 20MB.
What I would do differently
Wails' WebView inconsistencies are real. WebKit on macOS and WebView2 on Windows do not behave identically. CSS that works perfectly on one platform occasionally needs tweaks
for the other. I would still choose Wails for the size and performance benefits, but budget time for platform-specific testing.
I underestimated the DynamoDB type system. I thought it would be a weekend project to add DynamoDB support. It took weeks. If I were starting over, I would prototype the
DynamoDB UI first since it was the riskiest piece.
Monaco is powerful but heavy for a WebView. Monaco is around 2-3MB of JavaScript. In a WebView-based app where you are optimizing for fast startup, it is noticeable. It is
still worth it — rebuilding a code editor from scratch would be absurd — but I explored lighter alternatives before accepting the tradeoff.
What is next
- PostgreSQL support — the most requested feature
- MongoDB support — another NoSQL engine that most SQL-focused tools handle poorly
- Linux builds — Wails supports Linux, I just need to set up the CI pipeline
- ER diagram visualization — auto-generated from foreign key relationships
- Query plan diff — compare EXPLAIN output before and after index changes
Try it out
DB Connect is free. I built it for my own workflow and am releasing it because the database tool space should not require a subscription or a gigabyte of disk space for basic
functionality.
- Download: https://shubhesh07.github.io/db-connect/
- Source: https://github.com/shubhesh07/db-connect
- Runs on: macOS (Intel + Apple Silicon) and Windows
If you work with MySQL, Redshift, or DynamoDB and are tired of juggling multiple tools, give it a shot. Issues and feature requests are welcome.
Top comments (0)