A developer recounts the pain of juggling existing MySQL clients, then details the architecture of his two‑month side project, Free My Query. The article breaks down the design choices—local desktop rendering, schema introspection, no‑code query builders, and optional SSH tunneling—while weighing scalability, consistency, and API surface against the simplicity of a monolithic client.
Why Building a Custom MySQL GUI Reveals Hidden Trade‑offs in Distributed Tooling

The problem: UI churn kills productivity
Every day I opened a different client—MySQL Workbench for diagramming, DBeaver for ad‑hoc queries, a web console for remote servers. The UI switches forced me to remember shortcuts, connection strings, and quirks of each tool. Even simple CRUD operations required copy‑pasting boilerplate, and visualizing foreign‑key relationships meant opening a separate diagram window and mentally stitching tables together. The friction added up to minutes lost per feature, and over weeks it became a measurable drag on delivery velocity.
The solution approach: a single‑purpose desktop client
I set out to create Free My Query, a lightweight Windows‑only GUI that bundles three core capabilities:
- Live ER diagrams – The client connects to a MySQL instance, runs
INFORMATION_SCHEMAqueries, and renders tables and relationships on the fly. No separate modeling step; the diagram updates whenever the schema changes. - No‑code CRUD – A form‑based editor lets users insert, update, and delete rows without writing SQL. Under the hood the client builds parameterised statements and executes them over a single persistent connection.
- Java code generation – Point the tool at a user table and receive ready‑to‑paste Java methods for login and authentication, saving repetitive boilerplate.
A fourth feature, SSH tunneling, is slated for the next release to simplify connections to remote databases behind firewalls.
Architectural sketch
- Language & runtime – The UI is built with JavaFX, giving a native‑look on Windows while keeping the codebase portable for future OS support.
- Data access layer – A thin wrapper around the official MySQL Connector/J handles connection pooling, transaction boundaries, and automatic reconnection. All schema‑introspection queries are cached for 30 seconds to avoid hammering the server.
- Diagram engine – I reused the open‑source GraphStream library to lay out tables as nodes. The layout algorithm runs locally, meaning the client never needs to ship a heavy graph‑processing service.
- Code generator – A simple template engine (StringTemplate) substitutes column names into pre‑written Java snippets. The generator runs synchronously; the output is displayed in a read‑only text area for copy‑paste.
Scalability implications
Horizontal vs. vertical scaling
Because the client is a desktop process, scaling is inherently vertical: the more RAM/CPU a developer’s machine has, the smoother the diagram rendering and query execution. There is no server component to horizontally scale across a fleet. This design works for the target audience—individual developers or small teams—but would hit limits if the same UI were expected to serve hundreds of concurrent users.
Consistency model
The tool talks directly to MySQL using the default isolation level (REPEATABLE READ). When the diagram is refreshed, the client re‑queries INFORMATION_SCHEMA and rebuilds the graph. If another developer alters the schema in the meantime, the local view can become stale for up to the cache timeout. To mitigate this, I added a manual refresh button and a small warning banner that appears when the schema version changes (detected via SELECT @@global.version_comment).
Network considerations
SSH tunneling, once implemented, will add an extra round‑trip for each query. To keep latency low, the client will establish a single persistent tunnel per connection profile, reusing it for all subsequent operations. This mirrors how DBeaver handles SSH, but the implementation is deliberately lightweight: the tunnel is spawned as a child process of the Java runtime, and its lifecycle is tied to the UI session.
API patterns and extensibility
Minimal public surface
Free My Query exposes only two public APIs:
ConnectionProfile– a JSON‑serialisable object containing host, port, credentials, and optional SSH settings.CodeGenRequest– a structure that specifies the target table and desired language (currently Java only).
Both are consumed by the UI and can be persisted to disk, enabling a simple import/export workflow. Keeping the API surface small reduces the chance of breaking changes and makes future language extensions easier.
Plug‑in possibility
I considered a plug‑in system (e.g., OSGi) early on, but the added complexity outweighed the benefit for a single‑purpose tool. Instead, the code generator is deliberately template‑driven; adding support for another language is as easy as dropping a new template file into the templates/ directory and restarting the app.
Trade‑offs you need to know
| Aspect | Decision | Why it matters |
|---|---|---|
| Platform | Windows‑only desktop app | Guarantees low latency and native look, but excludes macOS/Linux users. A future Electron rewrite could broaden reach at the cost of memory overhead. |
| Schema caching | 30‑second in‑memory cache | Reduces load on production DB, but may show stale diagrams. Manual refresh mitigates the risk. |
| No‑code CRUD | Parameterised statements generated on the fly | Eliminates SQL syntax errors for simple operations, yet complex queries still require the raw editor. |
| SSH tunneling | Planned, not yet shipped | Provides secure remote access, but introduces extra failure modes (tunnel breakage, key management). |
| Extensibility | Template‑based code generation | Easy to add languages, but lacks deeper ORM integration that a full SDK would provide. |
Lessons learned for future distributed tools
- Keep the data path short – Direct DB connections avoid the latency of a middle‑tier API, but they also tie the client’s availability to the database’s network posture.
- Cache with intent – Caching schema metadata is safe as long as you surface staleness to the user. A version‑check query is cheap and pays off.
- Expose a tiny, versioned API – When you later decide to offer a SaaS version of the GUI, a stable JSON contract for connection profiles will make the transition painless.
- Plan for security early – SSH tunneling is a must‑have for production use. Embedding the tunnel logic from day one avoids retrofitting a fragile solution later.
Where to try it
Free My Query is available for download at freemyquery.com. The binary includes an installer, a quick‑start guide, and a sample ConnectionProfile JSON file. The source code lives on GitHub under an MIT license, so anyone can fork, add a new language template, or contribute a Linux build.
If you’ve wrestled with the same UI churn, give Free My Query a spin and let me know which feature saved you the most time. The next iteration will focus on multi‑platform support and a plug‑in hook for custom code generators.

Comments
Please log in or register to join the discussion