A Lightweight, High-Performance Server Framework for Lua
Features โข Quick Start โข Examples โข Documentation โข Contributing
- ๐ High Performance - Handles 200,000+ requests/second with single-threaded architecture
- ๐งต Coroutine-Based - Clean async/await style code without callback hell
- ๐ Rich Protocols - Built-in support for TCP, UDP, HTTP, WebSocket, gRPC, TLS
- ๐พ Database Ready - Native MySQL, Redis, and Etcd integrations
- ๐ Security - Comprehensive crypto suite including JWT, AES, RSA, HMAC
- ๐ Observability - Prometheus metrics and structured logging out of the box
- ๐ง Developer Friendly - Hot reload, interactive debugger, and extensive APIs
# Clone the repository
git clone https://github.com/findstr/silly.git
cd silly
# Build (supports Linux, macOS, Windows)
make
# With OpenSSL support for TLS
make OPENSSL=ONCreate a file hello.lua:
local tcp = require "silly.net.tcp"
tcp.listen("127.0.0.1:8888", function(conn)
print("New connection from", conn:remoteaddr())
while true do
local data = conn:read("\n")
if not data then
print("Client disconnected")
break
end
conn:write("Echo: " .. data)
end
conn:close()
end)
print("Server listening on 127.0.0.1:8888")Run the server:
./silly hello.luaTest with telnet or netcat:
echo "Hello Silly!" | nc localhost 8888Benchmarked on Intel Core i7-10700 @ 2.90GHz using redis-benchmark:
| Test | Throughput (req/s) | Avg Latency | P99 Latency |
|---|---|---|---|
| PING_INLINE | 235,849 | 0.230ms | 0.367ms |
| PING_MBULK | 224,719 | 0.241ms | 0.479ms |
View Full Benchmark Results โ
local silly = require "silly"
local http = require "silly.net.http"
http.listen {
addr = "0.0.0.0:8080",
handler = function(stream)
local response_body = "Hello from Silly!"
stream:respond(200, {
["content-type"] = "text/plain",
["content-length"] = #response_body,
})
stream:close(response_body)
end
}
print("HTTP server listening on http://0.0.0.0:8080")local websocket = require "silly.net.websocket"
websocket.listen {
addr = "0.0.0.0:8080",
handler = function(sock)
print("Client connected:", sock.fd)
while true do
local data, typ = sock:read()
if not data or typ == "close" then
break
end
if typ == "text" then
sock:write("Echo: " .. data, "text")
end
end
sock:close()
end
}
print("WebSocket server listening on ws://0.0.0.0:8080")local silly = require "silly"
local mysql = require "silly.store.mysql"
local db = mysql.open {
addr = "127.0.0.1:3306",
user = "root",
password = "password",
database = "mydb",
charset = "utf8mb4",
max_open_conns = 10,
max_idle_conns = 5,
}
silly.fork(function()
local users, err = db:query("SELECT * FROM users WHERE age > ?", 18)
if users then
for _, user in ipairs(users) do
print(user.name, user.email)
end
else
print("Query failed:", err.message)
end
db:close()
end)For more examples, check out the tutorials in the documentation.
Comprehensive documentation is available at https://findstr.github.io/silly/
Silly uses a hybrid threading model for optimal performance:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Silly Framework โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโค
โ Worker Threadโ Socket Threadโ Timer Thread โMonitor โ
โ (Lua VM) โ (epoll/kqueueโ (10ms res) โ Thread โ
โ โ /iocp) โ โ โ
โ โข Coroutine โ โข I/O Events โ โข Timers โโข Healthโ
โ โข Business โ โข 65K conns โ โข Schedulers โ Check โ
โ Logic โ โ โ โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโ
Key design principles:
- Single-threaded business logic - No locks, no race conditions
- Asynchronous I/O - Event-driven socket operations
- Coroutine-based - Clean async code without callbacks
| Module | Description | Documentation |
|---|---|---|
silly.net |
TCP, UDP, HTTP, WebSocket, gRPC, TLS | API |
silly.store |
MySQL, Redis, Etcd | API |
silly.crypto |
AES, RSA, HMAC, Hash | API |
silly.sync |
Channel, Mutex, WaitGroup | API |
silly.security |
JWT authentication | API |
silly.metrics |
Prometheus metrics | API |
silly.logger |
Structured logging | API |
./silly main.lua [options]
Core Options:
-h, --help Display help message
-v, --version Show version
-d, --daemon Run as daemon
Logging:
-p, --logpath PATH Log file path
-l, --loglevel LEVEL Log level (debug/info/warn/error)
-f, --pidfile FILE PID file path
Custom Options:
--key=value Custom key-value pairsExample with custom options:
./silly server.lua --port=8080 --workers=4 --env=productionAccess in Lua:
local env = require "silly.env"
local port = env.get("port") -- "8080"
local workers = env.get("workers") -- "4"
local environment = env.get("env") -- "production"Run the complete test suite:
# Run all tests
make testall
# Run with address sanitizer (Linux/macOS)
make testSilly has minimal dependencies:
- Lua 5.4 (embedded)
- jemalloc (optional, for better memory allocation)
- OpenSSL (optional, for TLS support)
- zlib (embedded, for compression)
All dependencies are automatically built via Git submodules.
We welcome contributions! Please see CONTRIBUTING.md for details.
# Clone with submodules
git clone --recursive https://github.com/findstr/silly.git
# Build in debug mode
make test
# Format code
make fmtSilly is licensed under the MIT License.
- Lua - The elegant scripting language
- jemalloc - Scalable concurrent memory allocator
- OpenSSL - Robust cryptography toolkit
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Official Docs