A high-performance Rust CLI tool and library that automatically introspects SQLite databases and generates complete GraphQL APIs with TOML-based configuration. Built as a memory-safe alternative to traditional GraphQL servers, graph-sql acts as a lightweight gateway that pushes business logic to the database layer for maximum performance and simplicity.
🚀 NEW: graph-sql is now available as a standalone CLI application with TOML configuration! Create a simple config file and instantly serve any SQLite database as a GraphQL API.
🔒 Memory Safety: Leverages Rust's zero-cost abstractions and memory safety guarantees to eliminate entire classes of bugs common in traditional API servers.
🏗️ Database-First Architecture: Acts as a stateless gateway/middleman, letting SQLite handle business logic, authorization, and data processing for optimal performance.
For detailed documentation and more queries, see the examples directory.
⚠️ Development Status
This project is in active development. Breaking changes may occur without notice as we rapidly iterate and improve the library. While the core functionality is stable, the API may evolve significantly. For production use, please pin to a specific commit and thoroughly test any updates.
✅ Recommended for:
- Internal tools and admin panels
- Prototypes and MVPs
- Development and testing environments
- Low-risk applications
- Edge deployments and serverless functions
- High-traffic public APIs
- Mission-critical applications
- Applications requiring real-time features
- Complex authentication/authorization needs
📈 Production Guidelines:
- Pin to a specific commit for stability
- Thoroughly test updates before deployment
- Use for non-critical services first
- Consider it for internal tooling and admin interfaces
- Why graph-sql?
- Comparisons
- Installation
- Library API
- How It Works
- Features
- Feature Support Status
- Prerequisites
- Quick Start
- Examples
- GraphQL Schema Structure
- Database Schema Mapping
- Example Usage
- Configuration
- Architecture
- Deployment
- Development
- Current Limitations
- Roadmap
- Contributing
- License
- Acknowledgments
- Support
graph-sql was created to solve several key challenges in modern API development:
Traditional GraphQL servers written in languages like Node.js or Go can suffer from memory leaks, buffer overflows, and garbage collection pauses. graph-sql leverages Rust's zero-cost abstractions and compile-time memory safety to eliminate entire classes of bugs that plague production API servers.
Instead of building complex application logic in the API layer, graph-sql pushes business logic to where it belongs: the database. This approach offers:
- Better Performance: Database operations are faster than network calls
- Data Consistency: Business rules enforced at the data layer
- Simplified Architecture: Stateless gateway with no application state
- Natural Scaling: Multiple instances can serve the same database
SQLite is often underestimated but offers unique advantages:
- Edge Computing: Perfect for serverless and edge deployments
- Performance: Excellent for read-heavy workloads and significant writes
- Simplicity: Single file, no server setup, easy backup and replication
- Extensions: Support for sqlean and other extensions for advanced functionality
- ACID Compliance: Full transactions with excellent reliability
graph-sql is specifically designed for heavy-load scenarios:
- Minimal Resource Usage: Low memory footprint and CPU overhead
- Efficient Concurrency: Tokio async runtime for thousands of connections
- Stateless Design: Pure middleman enabling horizontal scaling
- Native Speed: Compiled binary performance comparable to C/C++
Feature | graph-sql | Hasura |
---|---|---|
Database Support | SQLite + extensions | PostgreSQL, MySQL, SQL Server, BigQuery |
Setup Complexity | Zero config, single binary | Moderate (Docker/Cloud) |
Target Use Case | High-performance gateway | Production, enterprise |
Memory Safety | Rust memory safety | Go (garbage collected) |
Business Logic | Database-first (SQLite) | Application-first (resolvers) |
Authentication | JWT → SQLite authorization | Built-in with multiple providers |
Performance | Heavy load optimized | Very fast, enterprise scale |
Deployment | Single binary | Docker/Kubernetes |
Learning Curve | Minimal | Moderate |
Feature | graph-sql | PostgREST |
---|---|---|
API Style | GraphQL | REST |
Database | SQLite | PostgreSQL |
Query Flexibility | High (GraphQL) | Moderate (REST) |
Learning Curve | GraphQL knowledge needed | REST-familiar |
Type Safety | Strong (Rust + GraphQL) | Moderate |
Feature | graph-sql | Supabase |
---|---|---|
Scope | GraphQL gateway/middleman | Full backend platform |
Database | SQLite + extensions | PostgreSQL |
Architecture | Stateless gateway | Full backend platform |
Business Logic | Database-first (SQLite) | Mixed (database + edge functions) |
Authentication | JWT → database authorization | Built-in authentication service |
Deployment | Single binary | Cloud + self-hosted |
Memory Safety | Rust memory safety | TypeScript/Node.js |
Performance Focus | Heavy load optimization | Platform completeness |
Choose graph-sql when:
- You want memory-safe, Rust-based performance
- You prefer database-first business logic
- You need simple, single-binary deployment
- You want to leverage SQLite's capabilities
- You need a lightweight, stateless gateway
Install graph-sql globally using cargo:
cargo install graph-sql --git https://github.com/karlrobeck/graph-sql.git
Quick Start:
# Serve any SQLite database as GraphQL API (uses default config.toml)
graph-sql serve
# Use custom config file
graph-sql serve -c my-config.toml
# Introspect and view schema
graph-sql introspect
# Save schema to file
graph-sql introspect -o schema.graphql
The CLI now uses TOML-based configuration for all settings. Create a
config.toml
file in your project directory:
[server]
host = "0.0.0.0"
port = 8000
[database]
database-url = "sqlite://my_database.db"
use-env = true # Use DATABASE_URL environment variable if available
migrations-path = "./migrations"
[graphql]
enable-playground = true
depth = 5
complexity = 5
Basic Commands:
# Start GraphQL server (uses config.toml in current directory)
graph-sql serve
# Use custom config file
graph-sql serve -c /path/to/my-config.toml
# Introspect schema to stdout
graph-sql introspect
# Save schema to file
graph-sql introspect -o schema.graphql
# Use environment variable (set use-env = true in config)
export DATABASE_URL="sqlite://production.db"
graph-sql serve
CLI Features:
- 📋 TOML Configuration - All settings defined in structured config files
- 🗄️ Automatic database creation - Creates SQLite files if they don't exist
- 🔧 Migration support - Optional migration directory path in config
- 🌍 Environment variables - Uses
DATABASE_URL
whenuse-env = true
- 📄 Schema export - Export GraphQL schema to files with
introspect
command - ⚙️ Flexible configuration - Customize host, port, database URL, and GraphQL settings
Add graph-sql to your Cargo.toml
:
[dependencies]
graph-sql = { git = "https://github.com/karlrobeck/graph-sql.git" }
async-graphql = "7.0.17"
async-graphql-axum = "7.0.17"
axum = "0.8.4"
sqlx = { version = "0.8.6", features = ["runtime-tokio-native-tls", "sqlite", "migrate"] }
tokio = { version = "1.47.0", features = ["full"] }
When using graph-sql as a library, it provides a simple, elegant API for integrating GraphQL into your Rust applications:
// Main introspection function
pub async fn introspect(pool: &SqlitePool) -> Result<SchemaBuilder, Error>
// Schema builder for customization
impl SchemaBuilder {
pub fn finish(self) -> Result<Schema<Query, Mutation, EmptySubscription>, Error>
// Additional customization methods available
}
🔥 Minimal Setup (3 lines):
let db = SqlitePool::connect("sqlite://app.db").await?;
let schema = graph_sql::introspect(&db).await?.finish()?;
let app = Router::new().route("/graphql", post_service(GraphQL::new(schema)));
🛠️ With Custom Configuration:
let schema = graph_sql::introspect(&db)
.await?
// Add custom resolvers, middleware, etc.
.finish()?;
🔄 With Hot Reloading (Development):
// Reintrospect when schema changes
let schema = graph_sql::introspect(&db).await?.finish()?;
graph-sql works seamlessly with popular Rust web frameworks:
- Axum ✅ (shown in examples)
- Actix-web ✅ (via async-graphql-actix-web)
- Warp ✅ (via async-graphql-warp)
- Tide ✅ (via async-graphql-tide)
Perfect for:
- ⚡ High-performance APIs - Memory-safe GraphQL gateway for heavy-load scenarios
- � Secure data services - Rust's memory safety eliminates common vulnerabilities
- 🏗️ Microservices architecture - Stateless gateway enabling horizontal scaling
- �🛠️ Admin panels - Auto-generated CRUD interfaces for content management
- 📊 Data exploration - Interactive GraphiQL interface for database exploration
- 🔄 Legacy modernization - Add secure GraphQL layer to existing SQLite applications
- 🏭 Production workloads - Single binary deployment for enterprise environments
- 📱 Mobile backends - High-performance API generation for mobile applications
graph-sql automatically transforms your SQLite databases into modern GraphQL services.
- Memory Safety: Rust's zero-cost abstractions eliminate buffer overflows, memory leaks, and other common API server vulnerabilities
- High Performance: Designed for heavy-load scenarios with minimal resource overhead and efficient concurrency
- TOML Configuration: Simple, structured configuration files for all server and database settings
- Database-First Architecture: Business logic lives in SQLite, not the application layer, for better performance and consistency
- Stateless Gateway: Pure middleman design enabling horizontal scaling and simple deployment
- Full CRUD Operations: Complete Create, Read, Update, Delete support through GraphQL mutations and queries
- Foreign Key Relationships: Automatic detection and mapping of foreign key relationships to GraphQL object relationships
- Type-Safe Schema: Generates GraphQL types that match your database schema with proper nullability
- Dynamic Schema Generation: Creates resolvers and types at runtime based on database introspection
- Built-in GraphiQL: Interactive GraphQL playground included for development and testing
- Single Binary Deployment: No runtime dependencies or complex installation requirements
- SQLite Extensions: Future support for sqlean and other SQLite extensions for advanced functionality
- ✅ Queries: List and view operations with pagination
- ✅ Mutations: Insert, update, delete operations
- ✅ Foreign Key Relationships: Automatic relationship field generation
- ✅ Type Safety: Proper nullable/non-nullable field mapping
- ✅ GraphiQL: Built-in interactive query interface
- ✅ CRUD Operations: Complete Create, Read, Update, Delete support
- ✅ Schema Introspection: Automatic GraphQL schema generation
- ✅ Multiple Frameworks: Axum, Actix-web, Warp, Tide support
- ❌ Subscriptions: Real-time updates (planned)
- ❌ Advanced Filtering: WHERE clauses beyond basic ID lookup
- ❌ Custom Resolvers: Plugin system for business logic
- ❌ Aggregations: COUNT, SUM, AVG operations
- ❌ Multi-database: PostgreSQL, MySQL support (planned)
- ❌ Advanced Auth: OAuth, JWT integration (planned)
- Rust 1.86.0+ (2024 edition)
- SQLite database (or let graph-sql create one for you)
# Install globally
cargo install graph-sql --git https://github.com/karlrobeck/graph-sql.git
# Create a config.toml file
cat > config.toml << EOF
[server]
host = "0.0.0.0"
port = 8000
[database]
database-url = "sqlite://my_app.db"
use-env = true
[graphql]
enable-playground = true
EOF
# Serve any database instantly
graph-sql serve
# Open http://localhost:8000 for GraphiQL interface
Basic setup in your main.rs
:
use async_graphql::http::GraphiQLSource;
use async_graphql_axum::GraphQL;
use axum::{Router, response::{Html, IntoResponse}};
use sqlx::SqlitePool;
use tokio::net::TcpListener;
async fn graphiql() -> impl IntoResponse {
Html(GraphiQLSource::build().endpoint("/").finish())
}
#[tokio::main]
async fn main() -> async_graphql::Result<()> {
// Connect to your SQLite database
let db = SqlitePool::connect("sqlite://your_database.db").await?;
// Let graph-sql introspect and generate the schema
let schema = graph_sql::introspect(&db).await?.finish()?;
// Set up your GraphQL server
let router = Router::new().route(
"/",
axum::routing::get(graphiql).post_service(GraphQL::new(schema)),
);
let listener = TcpListener::bind("0.0.0.0:8000").await?;
axum::serve(listener, router).await?;
Ok(())
}
That's it! graph-sql automatically:
- 🔍 Introspects your database schema
- 🏗️ Generates GraphQL types for all tables
- 🔗 Maps foreign keys to GraphQL relationships
- ⚡ Creates CRUD resolvers for all operations
For detailed documentation and more queries, see the examples directory.
The examples use graph-sql as a library and include their own database setup and migrations. To run the included examples:
# Navigate to an example directory
cd examples/blog
# Run the example (it will create the database and run migrations)
cargo run
# Open http://localhost:8000 for GraphiQL interface
Each example demonstrates library usage with:
- Automatic database creation
- Built-in migration handling
- Custom GraphQL server setup
- Interactive GraphiQL interface
- Blog System - Complete blog with posts, authors, and comments
- E-commerce - Product catalog with categories and orders
- Library - Book management with authors and borrowing
- Task Manager - Todo application with users and assignments
The blog example demonstrates a complete content management system with relationships between posts, authors, and comments.
graph-sql automatically generates GraphQL types based on your SQLite schema:
- Tables → GraphQL Object Types
- Columns → GraphQL Fields with appropriate types
- Foreign Keys → GraphQL Object Relationships
- Primary Keys → ID fields
- Nullable Columns → Optional GraphQL fields
SQLite Type | GraphQL Type |
---|---|
INTEGER | Int |
TEXT | String |
REAL | Float |
BLOB | String |
BOOLEAN | Boolean |
Once your server is running, you can execute GraphQL queries:
# Query all posts with author information
query {
posts {
id
title
content
author {
name
email
}
}
}
# Create a new post
mutation {
createPost(
title: "My New Post"
content: "This is the content"
authorId: 1
) {
id
title
}
}
graph-sql uses TOML configuration files for all settings. The CLI looks for
config.toml
in the current directory by default, or you can specify a custom
path with -c
.
[server]
host = "0.0.0.0" # Server bind address
port = 8000 # Server port
[database]
database-url = "sqlite://local.db" # Database connection string
use-env = true # Use DATABASE_URL env var if available
migrations-path = "./migrations" # Optional path to migration files
[graphql]
enable-playground = true # Enable GraphiQL interface
depth = 5 # Query depth limit
complexity = 5 # Query complexity limit
Server Section:
host
- Server bind address (default: "0.0.0.0")port
- Server port number (default: 8000)
Database Section:
database-url
- SQLite database connection stringuse-env
- If true, usesDATABASE_URL
environment variable when availablemigrations-path
- Optional directory containing SQL migration files
GraphQL Section (optional):
enable-playground
- Enable GraphiQL interactive interface (default: true)depth
- Maximum query depth allowed (default: 5)complexity
- Maximum query complexity allowed (default: 5)
Set use-env = true
in your config to enable environment variable support:
export DATABASE_URL="sqlite://production.db"
graph-sql serve # Uses DATABASE_URL instead of config database-url
graph-sql follows a database-first architecture:
- Introspection Layer - Analyzes SQLite schema
- Type Generation - Creates GraphQL types from database structure
- Resolver Generation - Builds CRUD operations automatically
- Gateway Layer - Stateless GraphQL server
# Install and run
cargo install graph-sql --git https://github.com/karlrobeck/graph-sql.git
graph-sql serve -d "sqlite://production.db" -p 8080
FROM rust:alpine as builder
RUN apk add --no-cache musl-dev
RUN cargo install --git https://github.com/karlrobeck/graph-sql.git
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY --from=builder /usr/local/cargo/bin/graph-sql /usr/local/bin/
COPY database.db /app/
COPY config.toml /app/
WORKDIR /app
CMD ["graph-sql", "serve"]
[Unit]
Description=graph-sql GraphQL API
After=network.target
[Service]
Type=simple
User=graph-sql
WorkingDirectory=/opt/graph-sql
ExecStart=/usr/local/bin/graph-sql serve
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Current Options:
- Vertical Scaling: Increase server resources
- Load Balancing: Multiple instances behind a load balancer
- Read Replicas: SQLite supports read-only replicas
- Caching: Add Redis/Memcached in front
Future Features:
- Connection pooling optimizations
- Query result caching
- Horizontal sharding support
- Performance monitoring and metrics
To contribute to graph-sql:
# Clone the repository
git clone https://github.com/karlrobeck/graph-sql.git
cd graph-sql
# Create a development config file
cat > config.toml << EOF
[server]
host = "0.0.0.0"
port = 8000
[database]
database-url = "sqlite://local.db"
use-env = true
[graphql]
enable-playground = true
depth = 5
complexity = 5
EOF
# Run tests
cargo test
# Run the main CLI application
cargo run -- serve
# Run examples
cd examples/blog
cargo run
- SQLite only (PostgreSQL and MySQL support planned)
- Basic authentication (OAuth and JWT support planned)
- Limited custom scalar types
- No subscription support yet
- JWT authentication and authorization integration
- SQLite extension support (starting with sqlean)
- Advanced filtering (WHERE clauses)
- Performance optimizations for heavy load scenarios
- Data loaders for N+1 query prevention
- Row-level security implementation in SQLite
- Real-time subscriptions (GraphQL subscriptions)
- Database function support for business logic
- Connection pooling and caching optimizations
- PostgreSQL support with same philosophy
- Multi-database support (PostgreSQL, MySQL) with database-first approach
- Advanced SQLite extensions ecosystem
- Performance monitoring and metrics
- Horizontal scaling tools and best practices
- Custom scalar types
- Docker containerization
- Cloud deployment guides
The database-first philosophy will extend to other databases:
- PostgreSQL - Row Level Security, stored procedures, custom types
- MySQL - Stored procedures, user-defined functions, triggers
- SQL Server - T-SQL procedures, user-defined functions, CLR integration
We welcome contributions! Please see our Contributing Guidelines for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT OR Apache-2.0 License - see the LICENSE file for details.
- Built with async-graphql
- Powered by SQLx
- Web framework by Axum
- Query building with SeaQuery
- Create an issue for bug reports
- Start a discussion for questions
- FAQ - Comprehensive answers to common questions
- Contributing Guide - Detailed contribution guidelines
- Examples - Complete example applications
graph-sql - Turning your SQLite database into a full-featured GraphQL API, effortlessly.