Skip to content

Ghost Architecture — Node.js, Ember.js, SQLite/MySQL and Handlebars

DodaTech Updated 2026-06-28 11 min read

In this tutorial, you'll explore Ghost architecture — how the Node.js backend, Ember.js admin panel, SQLite or MySQL database, and Handlebars template engine work together to serve content on every page request.

What You'll Learn

  • The high-level Ghost architecture and request lifecycle
  • Node.js and Express as the backend foundation
  • The Ember.js admin client and how it communicates with the API
  • SQLite vs MySQL — which to choose and why
  • Handlebars templating and how themes render content
  • The Ghost file structure and what each folder contains
  • How middleware and routing process requests

Why It Matters

Understanding Ghost's architecture helps you make better decisions about hosting, performance optimization, theme development, and troubleshooting. When something breaks, knowing how the pieces fit together lets you pinpoint the problem faster. When you need to customize Ghost beyond what the admin panel offers, architectural knowledge guides you to the right file, config, or API endpoint. This foundation makes every subsequent lesson in this series more meaningful.

Real-World Use

A developer deploys a Ghost site that starts getting slow as traffic grows. He knows Ghost runs on Node.js with a single-threaded event loop, so CPU-heavy operations block all requests. He identifies that image processing on upload is the bottleneck, offloads it to a background job, and configures a CDN for static assets. Without understanding the architecture, he would be guessing at solutions — upgrading the server, adding more RAM, or switching database, none of which would fix the actual problem.

Learning Path

flowchart LR
  A["What is Ghost?"] --> B["Ghost Architecture
You are here"]:::current B --> C["Ghost CLI"] C --> D["Ghost Editor"] D --> E["Ghost Installation"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

High-Level Architecture

A Ghost site has four main layers:

  1. Node.js server — the application backend that handles routing, business logic, and API requests
  2. Database — SQLite (development) or MySQL (production) storing all content, settings, and member data
  3. Admin client — an Ember.js single-page application served as the admin interface
  4. Theme layer — Handlebars templates that render the public-facing site

When a visitor loads your site, the request flows through these layers in order.

Request Lifecycle

flowchart LR
  A["Browser request"] --> B["Nginx/Caddy (reverse proxy)"]
  B --> C["Node.js (Ghost app)"]
  C --> D["Router"]
  D --> E{"Admin route?"}
  E -->|"Yes"| F["Serve Ember.js SPA"]
  E -->|"No"| G["Load theme + content"]
  G --> H["Query database"]
  H --> I["Render Handlebars template"]
  I --> J["Return HTML to browser"]

  style C fill:#38bdf8,color:#0f172a
  style H fill:#38bdf8,color:#0f172a
  style I fill:#38bdf8,color:#0f172a
  1. The browser sends an HTTP request to your domain.
  2. Nginx or Caddy (or another reverse proxy) forwards the request to the Ghost Node.js process.
  3. Ghost's Express router examines the URL path.
  4. If the path starts with /ghost/, Ghost serves the Ember.js admin application.
  5. For public URLs, Ghost loads the active theme and queries the database for content.
  6. Handlebars renders the content into a complete HTML page.
  7. The HTML is returned through the proxy to the browser.

Node.js Backend

Ghost runs on Node.js, the JavaScript runtime built on Chrome's V8 engine. This is a fundamental difference from WordPress (PHP) and Drupal (PHP), and it affects everything from hosting requirements to performance characteristics.

Why Node.js?

Node.js is event-driven and non-blocking. This means a single Node.js process can handle thousands of concurrent connections without creating a new thread for each one. For a publishing platform, this is ideal because most requests are I/O-bound (reading from the database, fetching files) rather than CPU-bound.

Express Framework

Ghost uses the Express web framework for routing and middleware. Express is the most popular Node.js web framework and provides a clean way to define routes, middleware, and error handling.

Key middleware in Ghost:

  • body-parser: Parses incoming request bodies (JSON, URL-encoded)
  • compression: Gzip-compresses responses
  • helmet: Sets security-related HTTP headers
  • cors: Handles cross-origin requests for the API
  • serve-static: Serves static files from the built assets directory

Key Dependencies

Ghost uses several key Node.js packages:

  • express: Web framework for routing and middleware
  • knex: SQL query builder for database access
  • bookshelf: ORM (Object-Relational Mapper) on top of knex
  • handlebars: Template engine for rendering themes
  • sharp: Image processing (resize, optimize)
  • nodemailer: Email sending (via Mailgun or SMTP)
  • stripe: Payment processing integration

Ember.js Admin Interface

The Ghost admin panel is a single-page application built with Ember.js. When you navigate to yourdomain.com/ghost/, the server serves the Ember.js application, which then handles all subsequent navigation within the admin interface.

The admin SPA communicates with the Ghost API (not directly with the database). Every action you take in the admin panel — creating a post, uploading an image, changing a setting — sends an API request to the Node.js backend.

Why Ember.js?

Ember.js is a mature JavaScript framework with strong conventions. It is well-suited for complex admin interfaces because it provides:

  • Built-in routing and state management
  • Two-way data binding for forms
  • A component-based UI architecture
  • Strong conventions that scale

The admin interface is separate from the public site. If you access the admin panel while the public site is cached or proxied through a CDN, the admin still works because it communicates directly with the API.

Database: SQLite vs MySQL

Ghost supports two database engines. The choice depends on your deployment context.

SQLite (Development Default)

When you run ghost install local, Ghost uses SQLite by default. SQLite stores the entire database in a single file (content/data/ghost.db).

Pros:

  • Zero configuration — no database server needed
  • Portable — the entire database is one file
  • Perfect for development and testing
  • Automatic backups mean copying one file

Cons:

  • Not suitable for production at scale
  • No concurrent write support (one writer at a time)
  • Limited performance under high concurrency

MySQL (Production)

For production deployments, Ghost recommends MySQL 8.0+. MySQL is a full relational database management system.

Pros:

  • Handles concurrent reads and writes
  • Better performance under load
  • Replication and clustering options
  • Industry standard for production web applications

Cons:

  • Requires a separate database server
  • More complex setup and maintenance
  • Additional hosting cost
# SQLite database location
ls content/data/ghost.db

# MySQL connection string in config
mysql://user:password@localhost:3306/ghost_db

Which One Should You Choose?

  • Development: SQLite. It is simpler and your local machine does not need a MySQL server.
  • Production: MySQL. It handles traffic and concurrent writes properly.
  • Low-traffic personal site: SQLite can work in production for very low traffic, but MySQL is recommended.

Handlebars Templating

Ghost uses Handlebars as its template engine. Handlebars is a logic-less templating language that keeps templates clean and separates presentation from logic.

How Templates Work

When Ghost renders a page, it:

  1. Retrieves the requested content from the database (post, page, tag, author)
  2. Collects the context data (site settings, navigation, etc.)
  3. Loads the appropriate Handlebars template file
  4. Merges the context data into the template
  5. Returns the rendered HTML

Template Context

In Handlebars, you access data using double curly braces:

<!-- Template accesses context properties -->
<h1>{{title}}</h1>
<p>{{excerpt}}</p>

Ghost provides built-in helpers for common publishing patterns:

<!-- Iterate over posts -->
{{#foreach posts}}
  <article>
    <h2><a href="{{url}}">{{title}}</a></h2>
    <p>{{excerpt words="30"}}</p>
  </article>
{{/foreach}}

<!-- Conditional content -->
{{#if featured}}
  <span class="featured-badge">Featured</span>
{{/if}}

<!-- Access settings -->
<a href="{{@site.url}}">{{@site.title}}</a>

File Structure

A standard Ghost installation has this structure:

ghost/
├── content/
│   ├── data/            # SQLite database file
│   ├── images/          # Uploaded images and media
│   ├── logs/            # Error and access logs
│   ├── settings/        # Settings and routes.yaml
│   ├── themes/          # Installed themes
│   └── adapters/        # Custom storage/email adapters
├── current/             # Symlink to current Ghost version
├── versions/            # Installed Ghost versions
├── config.production.json  # Production configuration
└── index.js             # Ghost entry point

The content/ directory is the only folder you need to modify directly. Everything else is managed by Ghost itself. This separation means you can update Ghost without losing your content, themes, or images.

Process Management

In production, Ghost runs as a Node.js process managed by a process manager:

  • Ghost CLI uses a built-in process manager (local development)
  • systemd — Linux service manager for production servers
  • PM2 — Node.js process manager with clustering and monitoring
  • Docker — Containerized deployment with Orchestration

The process manager ensures Ghost restarts after crashes, logs output, and manages environment variables.

Common Mistakes

  1. Thinking Ghost needs Apache: Ghost does not use Apache. It runs on Node.js and typically uses Nginx as a reverse proxy, not as a PHP handler. Beginners sometimes try to install Ghost on Apache-based shared hosting and fail.

  2. Confusing the admin SPA with the public site: The admin interface is a separate Ember.js application, not server-rendered HTML. If the API is down, the admin panel will load (it is static HTML/CSS/JS) but will show errors when trying to fetch data.

  3. Running SQLite in production without understanding the limits: SQLite can handle moderate traffic for a single-user blog, but it does not support concurrent writes. If you have multiple authors publishing simultaneously, you will encounter database-locked errors.

  4. Modifying files in current/: The current/ directory is a symlink to the currently installed Ghost version. Any changes you make there are lost when you update Ghost. Always put customizations in the content/ directory or your theme.

  5. Not configuring a reverse proxy: Ghost should always run behind a reverse proxy (Nginx or Caddy) in production. The reverse proxy handles SSL termination, static file serving, Caching, and security headers. Running Ghost directly on port 2368 without a proxy is insecure and impractical.

Practice Questions

  1. What database engines does Ghost support, and when should you use each? Answer: Ghost supports SQLite (development, low-traffic) and MySQL 8.0+ (production). Use SQLite for local development and testing. Use MySQL for production deployments with multiple users or moderate-to-high traffic.

  2. How does the Ember.js admin interface communicate with the Ghost backend? Answer: The admin interface is a single-page application that communicates with the Ghost REST API. Every action in the admin panel (creating posts, uploading images, changing settings) sends an API request to the Node.js backend.

  3. Why does Ghost need a reverse proxy in production? Answer: A reverse proxy like Nginx handles SSL termination (HTTPS), serves static files efficiently, provides caching, sets security headers, and forwards dynamic requests to the Ghost Node.js process. Running Ghost without a proxy exposes the Node.js process directly to the internet, which is insecure and less performant.

  4. Challenge: Set up Ghost locally with ghost install local. Examine the file structure — identify the SQLite database file, the themes folder, and the current symlink. Then use the Ghost Content API at http://localhost:2368/ghost/api/content/posts/ to inspect the API response structure.

FAQ

Can I use PostgreSQL with Ghost?

Ghost does not officially support PostgreSQL. The supported databases are SQLite (development) and MySQL 8.0+ (production). While you can potentially use a custom database adapter, it is not recommended and may break with updates.

What version of Node.js does Ghost require?

Ghost 5.x requires Node.js 18.x or 20.x (LTS versions). Using other Node.js versions may cause compatibility issues. Check the latest requirements at ghost.org/docs.

Does Ghost use Redis for caching?

Ghost does not use Redis by default. Caching is handled by the reverse proxy layer (Nginx) and a CDN (like Cloudflare or Fastly). For advanced setups, you can configure custom caching strategies at the proxy level.

Can I run multiple Ghost sites on one server?

Yes, but each Ghost instance needs its own Node.js process, database, and port. You can run multiple sites using PM2 with different ports and configure Nginx to route each domain to the correct port. The Ghost CLI also supports multi-site setups.

What happens if the Node.js process crashes?

Ghost uses a process manager (systemd, PM2, or the Ghost CLI's built-in manager) that automatically restarts the process if it crashes. In production, the reverse proxy can show a maintenance page during the restart window.

Mini Project

Your task: Document the full request lifecycle of your local Ghost installation.

  1. Install Ghost locally using ghost install local.
  2. Create a test post in the admin interface.
  3. Use browser developer tools (Network tab) to trace the HTTP requests made when loading the public site.
  4. Identify which requests hit the API and which serve static content.
  5. Draw an architecture diagram showing how the browser, Nginx (if configured), Node.js, database, and template engine interact.
  6. Write a one-page architectural summary explaining each component's role.

This exercise gives you a mental model of how Ghost works internally — essential knowledge for troubleshooting and optimization.

What's Next

Now that you understand Ghost's architecture, it is time to learn the command-line tool that manages the entire platform:

Continue to Lesson 3: Ghost CLI — Install Ghost, manage processes, and run administrative commands from the terminal.

Related lessons:

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro