Tile38 is an open source (MIT licensed), in-memory geolocation data store, spatial index, and realtime geofencing server. It supports a variety of object types including lat/lon points, bounding boxes, XYZ tiles, Geohashes, and GeoJSON.
This README is quick start document. You can find detailed documentation at https://tile38.com.
Features
- Spatial index with search methods such as Nearby, Within, and Intersects.
- Realtime geofencing through webhooks or pub/sub channels.
- Object types of lat/lon, bbox, Geohash, GeoJSON, QuadKey, and XYZ tile.
- Support for lots of Clients Libraries written in many different languages.
- Variety of protocols, including http (curl), websockets, telnet, and the Redis RESP.
- Server responses are RESP or JSON.
- Full command line interface.
- Leader / follower replication.
- In-memory database that persists on disk.
Components
- tile38-server: The server
- tile38-cli: Command line interface tool
- tile38-benchmark: Server benchmark tool
Getting Started
Getting Tile38
Perhaps the easiest way to get the latest Tile38 is to use one of the pre-built release binaries which are available for OSX, Linux, FreeBSD, and Windows. Instructions for using these binaries are on the GitHub releases page.
Docker
To run the latest stable version of Tile38:
docker pull tile38/tile38
docker run -p 9851:9851 tile38/tile38
Visit the Tile38 hub page for more information.
Homebrew (macOS)
Install Tile38 using Homebrew
brew install tile38
tile38-server
Building Tile38
Tile38 can be compiled and used on Linux, OSX, Windows, FreeBSD, and probably others since the codebase is 100% Go. We support both 32 bit and 64 bit systems. Go must be installed on the build machine.
To build everything simply:
$ make
To test:
$ make test
Running
For command line options invoke:
$ ./tile38-server -h
To run a single server:
$ ./tile38-server
# The tile38 shell connects to localhost:9851
$ ./tile38-cli
> help
Prometheus Metrics
Tile38 can natively export Prometheus metrics by setting the --metrics-addr command line flag (disabled by default). This example exposes the HTTP metrics server on port 4321:
# start server and enable Prometheus metrics, listen on local interface only
./tile38-server --metrics-addr=127.0.0.1:4321
# access metrics
curl http://127.0.0.1:4321/metrics
If you need to access the /metrics endpoint from a different host you'll have to set the flag accordingly, e.g. set it to 0.0.0.0:> to listen on all interfaces.
Use the redis_exporter for more advanced use cases like extracting key values or running a lua script.
Playing with Tile38
Basic operations:
$ ./tile38-cli
# add a couple of points named 'truck1' and 'truck2' to a collection named 'fleet'.
> set fleet truck1 point 33.5123 -112.2693 # on the Loop 101 in Phoenix
> set fleet truck2 point 33.4626 -112.1695 # on the I-10 in Phoenix
# search the 'fleet' collection.
> scan fleet # returns both trucks in 'fleet'
> nearby fleet point 33.462 -112.268 6000 # search 6 kilometers around a point. returns one truck.
# key value operations
> get fleet truck1 # returns 'truck1'
> del fleet truck2 # deletes 'truck2'
> drop fleet # removes all
Tile38 has a ton of great commands.
Fields
Fields are extra data that belongs to an object. A field is always a double precision floating point. There is no limit to the number of fields that an object can have.
To set a field when setting an object:
> set fleet truck1 field speed 90 point 33.5123 -112.2693
> set fleet truck1 field speed 90 field age 21 point 33.5123 -112.2693
To set a field when an object already exists:
> fset fleet truck1 speed 90
To get a field when an object already exists:
> fget fleet truck1 speed
Searching
Tile38 has support to search for objects and points that are within or intersects other objects. All object types can be searched including Polygons, MultiPolygons, GeometryCollections, etc.

Within
WITHIN searches a collection for objects that are fully contained inside a specified bounding area.

Intersects
INTERSECTS searches a collection for objects that intersect a specified bounding area.

Nearby
NEARBY searches a collection for objects that intersect a specified radius.
Search options
WHERE - This option allows for filtering out results based on field values. For examplenearby fleet where speed 70 +inf point 33.462 -112.268 6000 will return only the objects in the 'fleet' collection that are within the 6 km radius and have a field named speed that is greater than 70.
Multiple WHEREs are concatenated as and clauses. WHERE speed 70 +inf WHERE age -inf 24 would be interpreted as speed is over 70 and age is less than 24.
The default value for a field is always 0. Thus if you do a WHERE on the field speed and an object does not have that field set, the server will pretend that the object does and that the value is Zero.
WHERE expressions support the =~ operator for regex matching. It uses Go's re2 regular expression engine to match string values in fields or GeoJSON properties within objects. For example, WHERE properties.name =~ 'truck.*' filters objects where the 'name' property matches the pattern, and WHERE field_name =~ 'value.*' works similarly for fields.
MATCH - MATCH is similar to WHERE except that it works on the object id instead of fields.nearby fleet match truck* point 33.462 -112.268 6000 will return only the objects in the 'fleet' collection that are within the 6 km radius and have an object id that starts with truck. There can be multiple MATCH options in a single search. The MATCH value is a simple glob pattern.
CURSOR - CURSOR is used to iterate though many objects from the search results. An iteration begins when the CURSOR is set to Zero or not included with the request, and completes when the cursor returned by the server is Zero.
NOFIELDS - NOFIELDS tells the server that you do not want field values returned with the search results.
LIMIT - LIMIT can be used to limit the number of objects returned for a single search request.
Geofencing
A
readme truncated — read the full docs on github