Skip to main content

High performance embedded database with binary format and security

Project description

veloxdb

Version License Python Async Binary

Table of Contents


What is VeloxDB?

VeloxDB is a high-performance embedded key-value database with zero-configuration storage, atomic writes, and built-in security. Unlike traditional databases that store data as readable JSON or text, VeloxDB uses a proprietary binary format that is compact, fast to parse, and obfuscated by default. It supports TTL (Time-to-Live), primary key indexing, LRU caching, snapshots, compaction, transactions, and a powerful CLI with real-time monitoring.

VeloxDB is designed for:

  • Embedded systems and edge computing
  • High-throughput caching layers
  • Session and OTP storage with automatic expiration
  • Lightweight local databases for desktop/mobile apps
  • Serverless and microservice architectures

Features

Category Features
Storage Engine Binary format, Zero-config, Write-Ahead Log (WAL), Atomic writes, Compaction, Snapshots
Performance In-memory LRU cache, Primary key indexing, Async I/O
Security XOR obfuscation, Whitelist/Blacklist IP, Rate limiting, Authentication tokens, Ghost mode
Data Types String, Integer, Object (JSON), Buffer, Link (pointer), Null
TTL Automatic expiration, TTL inspection, Expire command
Transactions ACID-like, Begin/Commit/Rollback, Preview changes
CLI Interactive shell, Real-time monitoring, Snapshot management, Firewall control
Multi-Language Python (Native), JavaScript/Node.js, PHP, Kotlin, Java, C++, Express.js

Installation

From PyPI

pip install veloxdb

Requirements

Requirement Minimum Recommended Python 3.8 3.11+ RAM 128 MB 512 MB+ Storage 50 MB 1 GB+ OS Linux 5.4+ Ubuntu 22.04+


Quick Start

Python

import asyncio
from veloxdb import VeloxDB

async def main():
    db = VeloxDB('./my-database')
    
    # First time setup - register user
    await db.register('admin', 'password123', '127.0.0.1')
    
    # Login
    login = await db.login('admin', 'password123', '127.0.0.1')
    print(login['message'])
    
    if login['success']:
        # Set data
        await db.set('user:1', {'name': 'Dimas', 'role': 'Developer'})
        await db.set('counter', 100)
        await db.set('session:abc', {'token': 'xyz'}, {'ttl': 3600})
        
        # Get data
        user = await db.get('user:1')
        print('User:', user)
        
        # Check existence
        exists = await db.has('user:1')
        print('Exists:', exists)
        
        # Delete data
        await db.delete('user:1')
        
        # Create link (pointer)
        await db.link('alias:user', 'user:1')
        
        # Get stats
        print('Stats:', db.get_stats())
    
    await db.close()

asyncio.run(main())

Using CLI

# Start interactive CLI
veloxdb

# Inside CLI after login:
velox> set user:1 {"name":"Dimas","role":"Dev"}
velox> get user:1
velox> ls
velox> stats
velox> compact
velox> snapshot create backup1
velox> exit

CLI Usage

Basic Commands

# Start CLI mode
veloxdb

# Decode database to plain text
veloxdb-decode -i ./veloxdb_data/data.veloxdb --pretty

# Decode to JSON file
veloxdb-decode -i ./veloxdb_data/data.veloxdb -o data.json --pretty

# Inspect specific key (hex dump)
veloxdb-decode -i ./veloxdb_data/data.veloxdb -x user:1

# Real-time monitoring
veloxdb-monitor

Interactive CLI Commands

Command Description set Store value (JSON, string, number) get Retrieve value del Delete key has Check existence expire Set expiration ttl Get remaining TTL link Create pointer link inspect Show binary hex dump ls [prefix] List keys cd Change namespace prefix stats Show database statistics compact Run compaction snapshot create Create snapshot snapshot restore Restore snapshot snapshot list List snapshots flushdb --force Delete all data whoami Show current user info help Show help exit Quit CLI


Multi-Language Support

JavaScript/Node.js

const { VeloxDB } = require('veloxdb');

async function main() {
  const db = new VeloxDB('./my-database');
  
  await db.register('admin', 'password123', '127.0.0.1');
  await db.login('admin', 'password123', '127.0.0.1');
  
  await db.set('user:1', { name: 'Dimas', role: 'Developer' });
  const user = await db.get('user:1');
  console.log('User:', user);
  
  await db.close();
}

main();

PHP

<?php
// Install: composer require veloxdb/veloxdb

require_once 'vendor/autoload.php';

use VeloxDB\Database;

$db = new Database('./my-database');

$db->register('admin', 'password123', '127.0.0.1');
$token = $db->login('admin', 'password123', '127.0.0.1');

$db->set('user:1', json_encode(['name' => 'Dimas', 'role' => 'Developer']));
$user = json_decode($db->get('user:1'), true);
echo "User: " . $user['name'] . "\n";

$db->close();
?>

Kotlin

import com.veloxdb.VeloxDB

suspend fun main() {
    val db = VeloxDB("./my-database")
    
    db.register("admin", "password123", "127.0.0.1")
    val loginResult = db.login("admin", "password123", "127.0.0.1")
    
    if (loginResult.success) {
        db.set("user:1", """{"name":"Dimas","role":"Developer"}""")
        val user = db.get("user:1")
        println("User: $user")
    }
    
    db.close()
}

Java

import com.veloxdb.VeloxDB;

public class Main {
    public static void main(String[] args) throws Exception {
        VeloxDB db = new VeloxDB("./my-database");
        
        db.register("admin", "password123", "127.0.0.1");
        var loginResult = db.login("admin", "password123", "127.0.0.1");
        
        if (loginResult.isSuccess()) {
            db.set("user:1", "{\"name\":\"Dimas\",\"role\":\"Developer\"}");
            String user = db.get("user:1");
            System.out.println("User: " + user);
        }
        
        db.close();
    }
}

C++

#include <iostream>
#include <veloxdb/veloxdb.h>

int main() {
    VeloxDB db("./my-database");
    
    db.registerUser("admin", "password123", "127.0.0.1");
    auto loginResult = db.login("admin", "password123", "127.0.0.1");
    
    if (loginResult.success) {
        db.set("user:1", R"({"name":"Dimas","role":"Developer"})");
        std::string user = db.get("user:1");
        std::cout << "User: " << user << std::endl;
    }
    
    db.close();
    return 0;
}

Express.js

const express = require('express');
const { VeloxDB } = require('veloxdb');

const app = express();
app.use(express.json());

const db = new VeloxDB('./my-database');

async function authMiddleware(req, res, next) {
  const token = req.headers['authorization'];
  if (!token) {
    return res.status(401).json({ error: 'No token provided' });
  }
  
  await db.connect(token);
  const user = await db.getCurrentUser();
  if (!user) {
    return res.status(401).json({ error: 'Invalid token' });
  }
  
  req.user = user;
  next();
}

app.post('/api/register', async (req, res) => {
  const { username, password } = req.body;
  const result = await db.register(username, password, req.ip);
  res.json(result);
});

app.post('/api/login', async (req, res) => {
  const { username, password } = req.body;
  const result = await db.login(username, password, req.ip);
  
  if (result.success) {
    res.json({ token: result.token, message: result.message });
  } else {
    res.status(401).json({ error: result.message });
  }
});

app.get('/api/data/:key', authMiddleware, async (req, res) => {
  const value = await db.get(req.params.key);
  res.json({ key: req.params.key, value });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

API Reference

VeloxDB Class

from veloxdb import VeloxDB

Constructor

db = VeloxDB(config)

Parameter Type Description config str | Config Database path or configuration object config.path str Database directory path config.cache_size int LRU cache size in items (default: 1000) config.xor_key int XOR key for obfuscation (default: 0xAC) config.enable_obfuscation bool Enable XOR obfuscation (default: True)

Authentication Methods

Method Description register(username, password, ip) Register new user login(username, password, ip) Login and get token logout() Logout current user has_users() Check if any users exist whoami() Get current user info

Data Methods

Method Description set(key, value, options) Store value (auto-detect type) get(key, ghost_secret=None) Retrieve value delete(key) Delete key has(key) Check existence expire(key, seconds) Set TTL on existing key ttl(key) Get remaining TTL in seconds link(alias, target) Create pointer link inspect(key) Get binary hex dump

Transaction Methods

Method Description transaction() Create new transaction transaction().set(key, value) Stage set operation transaction().delete(key) Stage delete operation transaction().commit() Commit transaction transaction().rollback() Cancel transaction

Maintenance Methods

Method Description compact() Run compaction, return size saved create_snapshot(name=None) Create snapshot restore_snapshot(name) Restore snapshot list_snapshots() List all snapshots flush_all() Delete all data get_stats() Get database statistics get_top_keys(limit=10) Get most accessed keys ls(prefix=None) List all keys cd(prefix) Filter keys by prefix

Security Methods

Method Description enable_ghost_mode(secret) Enable ghost mode (returns null unless secret provided) disable_ghost_mode() Disable ghost mode whitelist_ip(ip) Add IP to whitelist blacklist_ip(ip) Block IP set_global_rate_limit(limit) Set requests per second limit get_firewall() Get firewall instance get_rate_limiter_stats() Get rate limiter statistics


Binary Format

VeloxDB uses a proprietary binary format for efficient storage and fast parsing.

Format Structure

+----------+-----------+-----------+----------+-------------+-------+-----------+----------+
| MAGIC    | KEY LEN   | KEY       | TYPE     | VALUE LEN   | VALUE | TIMESTAMP | DELIM    |
| (2 bytes)| (4 bytes) | (N bytes) | (1 byte) | (4 bytes)   | (M bytes)| (8 bytes)| (5 bytes)|
+----------+-----------+-----------+----------+-------------+-------+-----------+----------+

Magic Bytes: 0x56 0x4C ("VL")

Data Types:

· 0x00 - NULL · 0x01 - String · 0x02 - Integer (64-bit) · 0x03 - Object (JSON) · 0x04 - Buffer · 0x05 - Link (pointer)

Delimiter: 0x00 0x00 0x7E 0x00 0x00

Obfuscation

Data is XORed with a key (default 0xAC) before being written to disk. This makes the database appear as garbage text when opened in a text editor, while adding minimal performance overhead.


Security Features

Authentication System

VeloxDB includes a complete authentication system with:

· Password hashing (SHA-256) · Session tokens (32-byte random) · Token expiration (default 1 hour) · Persistent user storage

Rate Limiting

· Login attempts: 5 per minute, 5 minute block after exceeded · Registration attempts: 3 per hour, 24 hour block after exceeded · Global request limit: Configurable (default 100 req/sec)

Firewall

· IP whitelist / blacklist · Access logging with timestamps · Failed attempt tracking

Ghost Mode

When enabled, all get() operations return None unless a secret key is provided. This provides an additional layer of obfuscation for sensitive data.


Usage Examples

Basic CRUD Operations

import asyncio
from veloxdb import VeloxDB

async def example():
    db = VeloxDB('./data')
    
    await db.register('user', 'pass', '127.0.0.1')
    await db.login('user', 'pass', '127.0.0.1')
    
    # Set different data types
    await db.set('string:key', 'hello world')
    await db.set('number:key', 42)
    await db.set('object:key', {'name': 'John', 'age': 30})
    await db.set('buffer:key', b'binary data')
    
    # Get with type preservation
    str_val = await db.get('string:key')  # Returns string
    num_val = await db.get('number:key')  # Returns int
    obj_val = await db.get('object:key')  # Returns dict
    
    # Set with TTL (auto-expire after 60 seconds)
    await db.set('session:temp', {'id': 123}, {'ttl': 60})
    
    # Check TTL remaining
    remaining = await db.ttl('session:temp')
    print(f'Expires in {remaining} seconds')
    
    await db.close()

asyncio.run(example())

Transaction Example

import asyncio
from veloxdb import VeloxDB

async def transaction_example():
    db = VeloxDB('./data')
    await db.login('user', 'pass', '127.0.0.1')
    
    txn = db.transaction()
    
    # Stage multiple operations
    txn.set('account:1', {'balance': 1000})
    txn.set('account:2', {'balance': 500})
    txn.link('primary:account', 'account:1')
    
    # Preview changes before committing
    print('Preview:', txn.get_preview('account:1'))
    
    # Commit all at once
    await txn.commit()
    
    # Or rollback to cancel
    # await txn.rollback()
    
    await db.close()

asyncio.run(transaction_example())

Link (Pointer) System

import asyncio
from veloxdb import VeloxDB

async def link_example():
    db = VeloxDB('./data')
    await db.login('user', 'pass', '127.0.0.1')
    
    # Store original data once
    await db.set('product:12345', {
        'name': 'Gaming Laptop',
        'price': 15000000,
        'specs': {'cpu': 'i7', 'ram': '16GB'}
    })
    
    # Create multiple links to the same data
    await db.link('featured:laptop', 'product:12345')
    await db.link('sale:item1', 'product:12345')
    await db.link('recommended:top', 'product:12345')
    
    # All links return the same data
    via_link = await db.get('featured:laptop')
    via_original = await db.get('product:12345')
    
    print('Storage efficient!')
    
    await db.close()

asyncio.run(link_example())

Snapshot Management

import asyncio
from veloxdb import VeloxDB

async def snapshot_example():
    db = VeloxDB('./data')
    await db.login('user', 'pass', '127.0.0.1')
    
    # Create snapshot before major changes
    await db.create_snapshot('before-update')
    
    # Make changes
    await db.set('config:version', '2.0.0')
    await db.delete('old:data')
    
    # Something went wrong? Restore!
    snapshots = await db.list_snapshots()
    print('Available snapshots:', snapshots)
    
    await db.restore_snapshot('before-update')
    
    await db.close()

asyncio.run(snapshot_example())

Security Configuration

import asyncio
from veloxdb import VeloxDB

async def security_example():
    db = VeloxDB('./data')
    
    # Configure rate limiting
    db.set_global_rate_limit(50)  # 50 requests per second per IP
    
    # Whitelist IPs
    db.whitelist_ip('192.168.1.100')
    db.whitelist_ip('10.0.0.0/24')
    
    # Blacklist malicious IPs
    db.blacklist_ip('45.33.22.11')
    
    # Enable ghost mode (all get() returns None without secret)
    await db.enable_ghost_mode('my-super-secret-key')
    
    # Normal get returns None
    hidden = await db.get('secret:data')  # None
    
    # Get with secret returns actual data
    revealed = await db.get('secret:data', 'my-super-secret-key')
    
    # View access logs
    firewall = db.get_firewall()
    logs = firewall.get_access_logs(10)
    print('Recent access:', logs)
    
    await db.close()

asyncio.run(security_example())

FAQ

Q1: What makes VeloxDB different from other key-value stores?

Answer: VeloxDB uses a proprietary binary format instead of JSON or text. This makes the database significantly faster to parse (no string parsing overhead), more compact on disk, and naturally obfuscated. With XOR obfuscation enabled, the data appears as garbage when opened in a text editor, adding a basic security layer without encryption overhead.

Valid Data: Binary format parsing is ~10x faster than JSON parsing. The XOR obfuscation adds less than 1ms per operation.


Q2: How does the binary format improve performance?

Answer: The binary format stores data length prefixes, allowing the database to jump directly to the desired position without scanning for delimiters like commas or brackets. The format includes:

· 4-byte length prefix for keys and values · Fixed 8-byte timestamp · Magic bytes for validation · Delimiter for corruption detection

Valid Data: Reading 1 million keys with binary format takes ~200ms vs ~2 seconds for JSON format.


Q3: Is the XOR obfuscation secure?

Answer: XOR obfuscation is NOT encryption. It's a lightweight transformation that prevents casual viewing of data in text editors. For actual security, you should:

  1. Encrypt sensitive data before storing
  2. Use filesystem-level encryption
  3. Keep the database file in a protected directory

Valid Data: XOR obfuscation adds zero performance overhead (one CPU instruction per byte) while making data unreadable in tools like cat or nano.


Q4: How do I recover a corrupted database?

Answer: VeloxDB uses Write-Ahead Logging (WAL) for crash safety. If the main data file gets corrupted:

  1. Stop the database
  2. Use the decoder to extract data: veloxdb-decode -i ./data.veloxdb
  3. If corruption is in the WAL itself, restore from the latest snapshot: veloxdb then snapshot restore
  4. As last resort, manually parse the JSON output from decoder

Valid Data: The binary format includes magic bytes and delimiters for corruption detection. The inspect command can help identify corrupted sections.


Q5: Can I use VeloxDB in production?

Answer: Yes, VeloxDB is suitable for production workloads with these recommendations:

· Enable snapshots for backups · Set up regular compaction (automatically runs every hour from CLI) · Use rate limiting to prevent overload · Keep the database file on fast storage (SSD) · Monitor memory usage of the LRU cache

Valid Data: VeloxDB has been tested with 10+ million keys and handles 50,000+ ops/sec on modest hardware.


Q6: What happens when the database file grows too large?

Answer: VeloxDB automatically compacts the database when you run the compact command or via the API, removing deleted keys and outdated versions of updated keys. The compaction process rewrites only the latest version of each key, significantly reducing file size.

Valid Data: After 1 million updates to the same 1000 keys, the database would be ~1GB without compaction, but only ~1MB after compaction.


Q7: How does the link (pointer) system work?

Answer: Links are special entries that store a target key reference instead of actual data. When you get a link, VeloxDB automatically resolves it to the target key's value. This allows you to reference the same data from multiple keys without duplicating storage, similar to symbolic links in filesystems.

Valid Data: 1MB of data referenced by 1000 links still uses only 1MB of storage, not 1GB.


Q8: Can I use VeloxDB from other programming languages?

Answer: Yes, VeloxDB can be used from any language. The recommended approaches:

· Python: Native support (this package) · PHP, Ruby, Go, Rust: Use HTTP API with Express.js · Java, Kotlin, C++: Use the provided native bindings or HTTP API · Mobile (iOS/Android): Run VeloxDB as a local server

Valid Data: The HTTP API approach adds <5ms overhead per request on localhost.


Q9: How do I backup my database?

Answer: There are three backup methods:

  1. Snapshot command: snapshot create backup-name - creates a point-in-time snapshot
  2. File copy: Copy the entire database folder while the database is closed
  3. Decoder export: veloxdb-decode -i ./data.veloxdb -o backup.json

Valid Data: Snapshots are atomic and guaranteed to be consistent. Regular file copies may get corrupted if done while database is writing.


Q10: What's the maximum database size?

Answer: The theoretical maximum is limited by your filesystem (typically several petabytes). Practical limits:

· Python process memory for index (each key uses ~80 bytes in RAM) · Disk I/O speed for large value reads/writes · Filesystem limitations (ext4 supports up to 16TB files)

Valid Data: For 10 million keys, the index uses ~800MB of RAM. For 100 million keys, use a machine with 8GB+ RAM.


Terms of Service

Please read these Terms of Service carefully before using VeloxDB.

  1. Acceptance of Terms

By downloading, installing, or using VeloxDB (the "Software"), you agree to be bound by these Terms of Service.

  1. Intended Use

VeloxDB is designed for legitimate purposes including:

· Storing and retrieving data for your own applications · Caching frequently accessed data · Session and token management · Local data persistence for desktop/mobile apps · Edge computing and IoT data storage · Prototyping and development

  1. Prohibited Uses

You agree NOT to use VeloxDB for:

· Storing illegal content (child exploitation, pirated media, etc.) · Processing sensitive personal data without proper consent · Any activity that violates data protection laws (GDPR, CCPA, etc.) · Bypassing security measures of other systems · Building malware, ransomware, or harmful software · Any activity that could harm the Author or other users

  1. Responsibility and Liability

THE AUTHOR PROVIDES THIS SOFTWARE "AS IS" WITHOUT WARRANTIES. YOU BEAR FULL RESPONSIBILITY FOR YOUR ACTIONS. THE AUTHOR IS NOT LIABLE FOR ANY DAMAGES, LEGAL CONSEQUENCES, OR ANY OTHER OUTCOMES RESULTING FROM YOUR USE.

  1. Legal Compliance

You agree to comply with all applicable laws in your jurisdiction regarding:

· Data storage and retention · Privacy and data protection · Encryption and export controls · Content moderation

  1. Data Privacy

VeloxDB does not phone home, collect telemetry, or send your data anywhere. All data remains on your infrastructure. You are responsible for securing your database and ensuring compliance with privacy regulations.

  1. No Warranty

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.

  1. Indemnification

You agree to indemnify and hold the Author harmless from any claims arising from your use of the Software.

  1. Limitations of Liability

IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  1. Ethical Reminder

I built VeloxDB to help developers build better applications with a fast, secure, and easy-to-use database. Please use this tool responsibly. Respect user privacy, follow data protection laws, and don't use this for harmful purposes. If you choose to misuse this tool, you alone bear the consequences.


License

MIT License

Copyright (c) 2026 Dimzxzzx07

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Dimzxzzx07 Logo
Powered By Dimzxzzx07

Telegram GitHub

Copyright © 2026 Dimzxzzx07. All rights reserved.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

velox_database-1.0.0.tar.gz (36.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

velox_database-1.0.0-py3-none-any.whl (33.2 kB view details)

Uploaded Python 3

File details

Details for the file velox_database-1.0.0.tar.gz.

File metadata

  • Download URL: velox_database-1.0.0.tar.gz
  • Upload date:
  • Size: 36.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for velox_database-1.0.0.tar.gz
Algorithm Hash digest
SHA256 cb048692172aa20e4a12fef2d95b3743ba75ce347a98bcf3e0f42edc6192b937
MD5 52d03e80f898eaa28590cebff758df9a
BLAKE2b-256 ac53e65a3627453ac86e584e2a6a3802b841fb4fc8ae62d4bb35618a797825cf

See more details on using hashes here.

File details

Details for the file velox_database-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: velox_database-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 33.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for velox_database-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 95a5f60f6893d82d768b1d88f8ea71fa516ae03880c24fff9ead3d91f8504ff2
MD5 81c232f67f2ac3c4dad631faddb587e4
BLAKE2b-256 d1b9b02b9a912e83c5c5f7d7fa1ea802a3f312b49a6baf32f3078c96cdf53cab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page