Accelerated Database Design: A 3‑Step Approach

How to design databases quickly, without unnecessary routine, and with seamless team collaboration.

Modern systems depend heavily on data integrity — the guarantee that information remains accurate, consistent, and trustworthy throughout its lifecycle. This article shows a battle‑tested workflow that replaces endless diagramming with a fast, text‑first process.

Modern systems rely heavily on data integrity — the assurance that information remains accurate, consistent, and trustworthy throughout its entire lifecycle.

Over the years, I’ve experimented with many tools for designing data storage systems. Most of them were graphical editors where you build the structure by dragging and arranging visual elements. Later, I switched to tools that rely on textual schema definitions and then render a diagram from that description. But those tools had their own drawback: they required writing a lot of repetitive, boilerplate text.

This eventually pushed me to create my own tool — one that began saving me an enormous amount of time. For example, when I needed to design a database for a CRM company providing roof-coating services, I compared both approaches. In a graphical editor, building the structure took around 4 hours, whereas with my text-first method it took only 1–2 hours. The reason is simple: you spend far less time positioning graphical elements, which helps maintain your flow of thought while designing the system.

Instead of endlessly dragging blocks in draw.io or dbdiagram.io, you can start with plain text — and then generate a clean UML diagram with a single click. The approach consists of just three steps:

  1. 1. Describe the application’s functionality in detail.
  2. 2. Define entities in a textual format — the so-called “anchors.”
  3. 3. Automatically generate the diagram.

In this article, we’ll break down each step, explore how the text-first approach works, and explain why it simplifies collaboration, change management, and performance optimization.

Why this approach is needed in the first place

The classic process of designing in graphical editors has several painful problems:

  • Adding a new entity → drag a new table onto the canvas → add fields one click at a time → draw relationships manually
  • Any structure change → rearrange everything again
  • No proper change history (Ctrl+Z doesn't count)
  • Hard to do code review of the data model
  • Impossible to quickly hand the model to an AI for analysis and suggestions

In large systems, even a single database issue related to poor modeling or missing constraints can lead to serious problems, especially when no clear design process is followed. Maintaining the structure manually increases the chance of misaligned relationships or missing constraints.

The text‑first approach solves all of these at once, letting you:

  • Edit the model several times faster
  • Keep full change history in Git
  • Let multiple people collaborate via Pull Requests
  • Hand the model to an AI agent for review and optimization

Step 1. Detailed description of the application's functionality

Before drawing tables, you need to clearly understand what the application will actually do and what data it will need. In other words, define the scope of data flowing through your system and maintain data integrity meaning within your application domain.

This is crucial because even the best database administrator or architect can't design a proper schema without knowing real user scenarios. Write in plain text — the main thing is that it's clear what actions the user performs and what data is created, changed, or displayed in the process.

Examples of good feature descriptions

Example 1. Registration

Users can sign up using email + password or via Google/Apple (OAuth 2.0). When registering with email, they receive an activation link. Until they click the link, the account is considered unactivated. Clear data flow like this helps later define constraints such as primary keys and indexing strategies.

Example 2. Money transfer

A user can transfer money from one of their cards to any other card. They select the source card, enter the recipient's card number and amount (not exceeding the available balance). The system checks the recipient card via the banking registry, shows the recipient's name and the fee. After confirmation, the transfer is executed. Transaction history is available for each card. Flows like these often require database encryption and distributed components, and can later be optimized with indexing strategies.

Example 3. Doctor's appointment booking

A patient selects a doctor, chooses an available time slot, and books an appointment. After confirmation, the doctor receives a notification. The doctor sees their appointments in a calendar, can open a booking card, and view patient details.

Golden rule: describe the application's behavior, not the entire domain. If a field is only displayed on screen and doesn't affect anything else, you can skip it for now — you'll add it later.

All application documentation is stored in a single file — whether it’s a DOCX document or a corporate wiki. However, in practice, it’s better to keep it in Git alongside the anchor definitions in Markdown format.

The application description document accompanies the project throughout its entire lifecycle. It records the current state of the system: which mechanics have already been implemented, which processes are supported, and how the key parts of the application function. Every new feature first appears as a textual description in this file, and only after that is it reflected in the data model.

This approach has several advantages:

  • Transparency of the data structure. It becomes much easier to understand what the current database schema represents and what functionality each part of the data supports.
  • Faster onboarding. New developers, analysts, and other team members can get up to speed more quickly thanks to a single, up-to-date source of documentation.
  • Improved performance of AI agents. A rich descriptive context enhances the quality of interaction with AI tools, especially when using agents within the project.

Step 2. Entity description — "anchors"

After describing the functionality, the next stage is identifying the main anchors (data entities) that define the data structure and the relationships between them. At this stage, the previously described functionality is very helpful because you can compare the database schema with the functional requirements.

The process looks like this:

  • Create the database schema.
  • Re-read the application description and analyze whether the functionality can be implemented based on the current schema.
  • If everything is feasible, proceed further.
  • If inconsistencies are found, update the database schema.

Example

Users can create reminders with a date, time, and optional recurrence settings (daily, weekly, weekdays). After saving, the reminder is placed in a background service queue that periodically checks upcoming events. When the reminder time comes, the service sends a push notification to the user's device. If the user dismisses or opens the notification, the reminder status is updated (for example, "completed" or "snoozed"). A strict data structure allows uniquely identifying reminders and optimizing indexing by execution time and status.

While re-reading this description, you realize that you created the anchors:

  • User
  • Reminder
  • PushNotification

But then you notice that the schema is missing the reminder status, which is necessary for the described functionality. At this point of reviewing requirements and the DB schema, you identify this gap and add the Status field to the Reminder entity.

Textual Description of the Database Structure

All defined anchors are stored in a single file. To enable versioning of the schema, it is recommended to place this file in a Git repository.

The structure of the file is as simple as possible. It contains only the described anchors in a specific record format. Each anchor consists of two elements: the anchor name and the fields it contains.

The fields, in turn, include the field name, data type, NULL or NOT NULL constraint, and a flag indicating whether it is a foreign key.

Anchor format

EntityName
    Field: type // optional comment
    AnotherField: type?
    ForeignKeyId: int FK(OtherEntity)

Example anchors for the doctor appointment system

User // regular system users
    Id: int
    Name: str
    DateBirth: datetime
    PhoneNumber: str
    DateRegistration: datetime

Patient // patients (extends User)
    Id: int
    UserId: int FK(User)
    CreatedAt: datetime

Doctor // doctors (also extends User)
    Id: int
    UserId: int FK(User)
    PhoneNumber: str
    GotJobAt: datetime
    ResignedAt: datetime? // can be NULL
    CurrentlyWorking: bool
    Rating: float

WorkSchedule // doctors' working schedule
    Id: int
    DoctorId: int FK(Doctor)
    Day: enum //(Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday)
    StartTime: time
    EndTime: time

AppointmentBooking // appointment bookings
    Id: int
    PatientId: int FK(Patient)
    DoctorId: int FK(Doctor)
    RecordedOn: datetime
    Status: enum //(Pending, Confirmed, Completed, Canceled)

While writing anchors, it becomes easy to define primary key constraints and foreign key relationships. For example, you can immediately see whether a composite primary key is needed or if a simple auto‑incrementing integer is enough.

Describing relationships textually also simplifies future steps such as adding foreign key constraints or planning indexing that will optimize queries later.

Why this is faster and more convenient than graphical editors:

  • Add an entity → just paste a new text block
  • Change a field → edit one line
  • Rename an entity → find + replace across the file
  • Everything is version‑controlled in Git

Step 3. Automatic UML diagram generation

When all anchors are ready (everything in one text file), you run a script — and get ready‑made Mermaid code.

How to do it

  1. Download the script from GitHub.
  2. Place all anchors in a file named model.txt.
  3. Run the program (to run it, you need to set up Python for this project).
  4. Select the path to the model.txt file.
  5. Copy the Mermaid script.
  6. Open the Mermaid Live Editor.
  7. Paste the code into the left panel.
  8. Switch to Playground mode and set Layout to Adaptive — the diagram becomes maximally readable.

This unified source of truth makes it easier to hand the schema to a database developer or integrate it with modern storage engines, depending on your project needs.

Go to GitHub

The Result

After completing all these steps, we obtain a clean, well-structured database diagram as the output. This visual representation clearly shows all entities, their relationships, and the data flow within the system, making it easy to understand the database structure at a glance.

Database Entity-Relationship Diagram

Summary: why you should try this approach

Anchors reduce routine effort and help you think more clearly about entities, indexing strategies, SQL database structure, and business logic. The difference becomes especially visible when you compare the "before" and "after" experience:

BenefitBeforeNow
Model history & code reviewalmost impossibleGit + Pull Request
Team collaborationdifficulteasy
Give model to AI for analysisimpossiblejust copy the text
Diagram freshnessquickly becomes outdatedalways up‑to‑date (generated)

Try this approach on your next project — you'll likely be surprised how much time and stress it saves, whether you're building a traditional relational database or experimenting with modern architectures.

Wrapping up

Anchors give you a lightweight, expressive way to design databases without drowning in diagram tools or losing context in screenshots. You keep everything in plain text, under version control, and always ready to feed into scripts, documentation, or AI assistants.

If you're tired of rearranging tables on an infinite canvas, try a text‑first modeling workflow — it's simple enough to start in minutes, yet powerful enough to support complex systems over the long term.