---
title: Database Design
description: MCD, MLD and MPD for MemeGoat.
---

## Conceptual Data Model (MCD)
The MCD defines entities and their relationships.

```mermaid
erDiagram
    USER ||--o{ MEME : "creates"
    USER ||--o{ COMMENT : "writes"
    MEME ||--o{ COMMENT : "receives"
    MEME }o--o{ TAG : "has"

    USER {
        string username
        string email
        string password
        datetime created_at
    }
    MEME {
        string title
        string image_url
        datetime created_at
    }
    TAG {
        string name
    }
    COMMENT {
        string content
        datetime created_at
    }
```

## Logical Data Model (MLD)
The MLD translates the MCD into tables with foreign keys.

```mermaid
erDiagram
    users ||--o{ memes : "user_id"
    users ||--o{ comments : "user_id"
    memes ||--o{ comments : "meme_id"
    memes ||--o{ meme_tags : "meme_id"
    tags ||--o{ meme_tags : "tag_id"

    users {
        uuid id PK
        varchar username
        varchar email
        text password_hash
        timestamp created_at
    }
    memes {
        uuid id PK
        varchar title
        text image_url
        uuid user_id FK
        timestamp created_at
    }
    tags {
        uuid id PK
        varchar name
    }
    meme_tags {
        uuid meme_id FK
        uuid tag_id FK
    }
    comments {
        uuid id PK
        text content
        uuid user_id FK
        uuid meme_id FK
        timestamp created_at
    }
```

## Physical Data Model (MPD)
SQL implementation for PostgreSQL.

```sql
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE memes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    title VARCHAR(255) NOT NULL,
    image_url TEXT NOT NULL,
    user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE tags (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(50) UNIQUE NOT NULL
);

CREATE TABLE meme_tags (
    meme_id UUID REFERENCES memes(id) ON DELETE CASCADE,
    tag_id UUID REFERENCES tags(id) ON DELETE CASCADE,
    PRIMARY KEY (meme_id, tag_id)
);

CREATE TABLE comments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    content TEXT NOT NULL,
    user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    meme_id UUID REFERENCES memes(id) ON DELETE CASCADE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
