Ghost Architecture — Node.js, Ember.js, SQLite/MySQL and Handlebars
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:
- Node.js server — the application backend that handles routing, business logic, and API requests
- Database — SQLite (development) or MySQL (production) storing all content, settings, and member data
- Admin client — an Ember.js single-page application served as the admin interface
- 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
- The browser sends an HTTP request to your domain.
- Nginx or Caddy (or another reverse proxy) forwards the request to the Ghost Node.js process.
- Ghost's Express router examines the URL path.
- If the path starts with
/ghost/, Ghost serves the Ember.js admin application. - For public URLs, Ghost loads the active theme and queries the database for content.
- Handlebars renders the content into a complete HTML page.
- 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:
- Retrieves the requested content from the database (post, page, tag, author)
- Collects the context data (site settings, navigation, etc.)
- Loads the appropriate Handlebars template file
- Merges the context data into the template
- 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
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.
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.
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.
Modifying files in
current/: Thecurrent/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 thecontent/directory or your theme.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
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.
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.
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.
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 athttp://localhost:2368/ghost/api/content/posts/to inspect the API response structure.
FAQ
Mini Project
Your task: Document the full request lifecycle of your local Ghost installation.
- Install Ghost locally using
ghost install local. - Create a test post in the admin interface.
- Use browser developer tools (Network tab) to trace the HTTP requests made when loading the public site.
- Identify which requests hit the API and which serve static content.
- Draw an architecture diagram showing how the browser, Nginx (if configured), Node.js, database, and template engine interact.
- 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:
- Ghost Config — Configure your Ghost installation
- Ghost Admin — Navigate the admin dashboard
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro