{"id":42511420,"url":"https://github.com/fluree/server","last_synced_at":"2026-01-28T14:12:48.740Z","repository":{"id":187040556,"uuid":"621855514","full_name":"fluree/server","owner":"fluree","description":"Fluree Server - Operates Fluree in consensus, fault-tolerant, redundant","archived":false,"fork":false,"pushed_at":"2026-01-14T15:43:04.000Z","size":1013,"stargazers_count":21,"open_issues_count":27,"forks_count":2,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-14T19:16:48.963Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluree.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-31T14:31:01.000Z","updated_at":"2026-01-12T13:59:09.000Z","dependencies_parsed_at":"2023-10-30T22:27:29.885Z","dependency_job_id":"c7020d0a-9f06-42a7-9f5a-b553b320bff5","html_url":"https://github.com/fluree/server","commit_stats":null,"previous_names":["fluree/server"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/fluree/server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluree%2Fserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluree%2Fserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluree%2Fserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluree%2Fserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluree","download_url":"https://codeload.github.com/fluree/server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluree%2Fserver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T13:02:32.985Z","status":"ssl_error","status_checked_at":"2026-01-28T13:02:04.945Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-28T14:12:47.902Z","updated_at":"2026-01-28T14:12:48.732Z","avatar_url":"https://github.com/fluree.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fluree Server\n\nFluree Server wraps the [fluree/db](https://github.com/fluree/db) library with\nan HTTP API server and consensus capabilities. While fluree/db can be used\ndirectly in applications for embedded database functionality, Fluree Server\nprovides the infrastructure needed for multi-client environments requiring\nconsistent transaction ordering, ledger state management, and distributed\nconsensus.\n\nThe server can run as either a consensus-participating node for transaction\nprocessing or as a query-only node for horizontal scaling. Multiple servers can\nform a cluster for fault tolerance and performance.\n\n**Key Features:**\n- **High Availability**: Automatic failover and work redistribution when\n  servers join or leave\n- **Guaranteed Ordering**: Consistent transaction processing across all nodes\n- **Horizontal Scaling**: Add query-only nodes for read performance\n- **Load Distribution**: Automatic workload balancing across consensus nodes\n- **Duplicate Prevention**: Built-in transaction deduplication\n\n## Quick Start\n\nThe quickest way to run Fluree Server with Docker:\n\n```bash\ndocker run -p 58090:8090 -v `pwd`/data:/opt/fluree-server/data fluree/server\n```\n\nOr run from source (requires Java 11+ and Clojure):\n\n```bash\n# Run directly without building JAR (development mode)\nmake run\n\n# Build and run in one command\nmake build-and-run\n\n# Run with custom config\njava -jar target/server-*.jar --config /path/to/config.jsonld\n```\n\nFor comprehensive documentation, visit\n[https://developers.flur.ee](https://developers.flur.ee).\n\nThe sections below cover custom configurations and building from source.\n\n## API Examples\n\nHere are examples using curl to demonstrate key Fluree Server features. These\nexamples assume the server is running on the default port 8090.\n\n### Create a New Ledger\n\n```bash\ncurl -X POST http://localhost:8090/fluree/create \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"ledger\": \"example/ledger\"\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 0,\n  \"tx-id\": \"089aeb0dd3a5cbef5cafd76aee57b71ff039ec35c9ce574daafa891c6c401381\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Insert Data\n\nAfter creating the ledger, you can add data using the `/insert` endpoint:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/insert \\\n  -H \"Content-Type: application/json\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '{\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"@graph\": [{\n      \"@id\": \"ex:alice\",\n      \"@type\": \"schema:Person\",\n      \"schema:name\": \"Alice Johnson\",\n      \"schema:email\": \"alice@example.com\"\n    }]\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 1,\n  \"tx-id\": \"f4de14124f6121125b20dace04f6867326639b786d65eb542a3d02e1d6c1787e\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Insert Additional Data\n\n```bash\ncurl -X POST http://localhost:8090/fluree/insert \\\n  -H \"Content-Type: application/json\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '{\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"@graph\": [{\n      \"@id\": \"ex:bob\",\n      \"@type\": \"schema:Person\",\n      \"schema:name\": \"Bob Smith\",\n      \"schema:email\": \"bob@example.com\",\n      \"schema:knows\": {\"@id\": \"ex:alice\"}\n    }]\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 2,\n  \"tx-id\": \"f4de14124f6121125b20dace04f6867326639b786d65eb542a3d02e1d6c1787e\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Query Data\n\n```bash\ncurl -X POST http://localhost:8090/fluree/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"from\": \"example/ledger\",\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"select\": {\"?person\": [\"*\"]},\n    \"where\": {\n      \"@id\": \"?person\",\n      \"@type\": \"schema:Person\"\n    }\n  }'\n```\n\nExpected output:\n```json\n[\n  {\n    \"@id\": \"ex:alice\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Alice Johnson\",\n    \"schema:email\": \"alice@example.com\"\n  },\n  {\n    \"@id\": \"ex:bob\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Bob Smith\",\n    \"schema:email\": \"bob@example.com\",\n    \"schema:knows\": {\"@id\": \"ex:alice\"}\n  }\n]\n```\n\n### SPARQL Query\n\nFluree also supports SPARQL queries. Put the ledger name in the `FROM` clause:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/query \\\n  -H \"Content-Type: application/sparql-query\" \\\n  -H \"Accept: application/sparql-results+json\" \\\n  -d '\n    PREFIX schema: \u003chttp://schema.org/\u003e\n    PREFIX ex: \u003chttp://example.org/\u003e\n    \n    SELECT ?person ?name ?email\n    FROM \u003cexample/ledger\u003e\n    WHERE {\n      ?person a schema:Person ;\n              schema:name ?name ;\n              schema:email ?email .\n    }\n  '\n```\n\nExpected output (SPARQL Results JSON format):\n```json\n{\n  \"head\": {\n    \"vars\": [\"person\", \"name\", \"email\"]\n  },\n  \"results\": {\n    \"bindings\": [\n      {\n        \"person\": {\n          \"type\": \"uri\",\n          \"value\": \"http://example.org/alice\"\n        },\n        \"name\": {\n          \"type\": \"literal\",\n          \"value\": \"Alice Johnson\"\n        },\n        \"email\": {\n          \"type\": \"literal\",\n          \"value\": \"alice@example.com\"\n        }\n      },\n      {\n        \"person\": {\n          \"type\": \"uri\",\n          \"value\": \"http://example.org/bob\"\n        },\n        \"name\": {\n          \"type\": \"literal\",\n          \"value\": \"Bob Smith\"\n        },\n        \"email\": {\n          \"type\": \"literal\",\n          \"value\": \"bob@example.com\"\n        }\n      }\n    ]\n  }\n}\n```\n\n### Insert More Data\n\nThe `/insert` endpoint adds new data to the ledger. If the subject already exists, the operation will merge the new properties with existing ones:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/insert \\\n  -H \"Content-Type: application/json\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '{\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"@graph\": [{\n      \"@id\": \"ex:charlie\",\n      \"@type\": \"schema:Person\",\n      \"schema:name\": \"Charlie Brown\",\n      \"schema:email\": \"charlie@example.com\"\n    }]\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 3,\n  \"tx-id\": \"...\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Update Data\n\nThe `/update` endpoint is the preferred way to modify existing data using `where`, `delete`, and `insert` clauses. This endpoint replaces the deprecated `/transact` endpoint:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/update \\\n  -H \"Content-Type: application/json\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '{\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"where\": {\n      \"@id\": \"?person\",\n      \"schema:email\": \"alice@example.com\"\n    },\n    \"delete\": {\n      \"@id\": \"?person\",\n      \"schema:email\": \"alice@example.com\"\n    },\n    \"insert\": {\n      \"@id\": \"?person\",\n      \"schema:email\": \"alice@newdomain.com\"\n    }\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 4,\n  \"tx-id\": \"...\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Upsert Data\n\nThe `/upsert` endpoint performs an \"update or insert\" operation. If the subject exists, it updates the properties; if not, it creates a new subject:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/upsert \\\n  -H \"Content-Type: application/json\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '{\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"@graph\": [{\n      \"@id\": \"ex:alice\",\n      \"schema:age\": 43\n    }, {\n      \"@id\": \"ex:diana\",\n      \"@type\": \"schema:Person\",\n      \"schema:name\": \"Diana Prince\",\n      \"schema:email\": \"diana@example.com\"\n    }]\n  }'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 5,\n  \"tx-id\": \"...\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Insert with Turtle Format\n\nThe `/insert` endpoint also supports Turtle (TTL) format for RDF data:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/insert \\\n  -H \"Content-Type: text/turtle\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '@prefix schema: \u003chttp://schema.org/\u003e .\n@prefix ex: \u003chttp://example.org/\u003e .\n\nex:emily a schema:Person ;\n    schema:name \"Emily Davis\" ;\n    schema:email \"emily@example.com\" ;\n    schema:age 28 .'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 6,\n  \"tx-id\": \"...\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n### Upsert with Turtle Format\n\nThe `/upsert` endpoint also accepts Turtle format:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/upsert \\\n  -H \"Content-Type: text/turtle\" \\\n  -H \"fluree-ledger: example/ledger\" \\\n  -d '@prefix schema: \u003chttp://schema.org/\u003e .\n@prefix ex: \u003chttp://example.org/\u003e .\n\nex:emily schema:jobTitle \"Senior Engineer\" .\nex:frank a schema:Person ;\n    schema:name \"Frank Wilson\" ;\n    schema:email \"frank@example.com\" .'\n```\n\nExpected output:\n```json\n{\n  \"ledger\": \"example/ledger\",\n  \"t\": 7,\n  \"tx-id\": \"...\",\n  \"commit\": {\n    \"address\": \"fluree:memory://...\",\n    \"hash\": \"...\"\n  }\n}\n```\n\n**Note:** The `/transact` endpoint is maintained for backward compatibility but `/update` should be preferred for all new implementations.\n\n### Time Travel: Query at a Specific Time\n\nQuery the ledger state at transaction 2:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"from\": \"example/ledger\",\n    \"t\": 2,\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"select\": {\"?person\": [\"*\"]},\n    \"where\": {\n      \"@id\": \"?person\",\n      \"@type\": \"schema:Person\"\n    }\n  }'\n```\n\nExpected output (shows state before Alice's email was updated):\n```json\n[\n  {\n    \"@id\": \"ex:alice\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Alice Johnson\",\n    \"schema:email\": \"alice@example.com\"\n  },\n  {\n    \"@id\": \"ex:bob\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Bob Smith\",\n    \"schema:email\": \"bob@example.com\",\n    \"schema:knows\": {\"@id\": \"ex:alice\"}\n  }\n]\n```\n\nQuery at a specific ISO-8601 timestamp:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"from\": \"example/ledger\",\n    \"t\": \"2025-01-15T10:30:00Z\",\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"select\": {\"?person\": [\"*\"]},\n    \"where\": {\n      \"@id\": \"?person\",\n      \"@type\": \"schema:Person\"\n    }\n  }'\n```\n\nExpected output (returns data as it existed at that timestamp):\n```json\n[\n  {\n    \"@id\": \"ex:alice\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Alice Johnson\",\n    \"schema:email\": \"alice@newdomain.com\"\n  },\n  {\n    \"@id\": \"ex:bob\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Bob Smith\",\n    \"schema:email\": \"bob@example.com\",\n    \"schema:knows\": {\"@id\": \"ex:alice\"}\n  }\n]\n```\n\nQuery the ledger state from 5 minutes ago using ISO-8601 relative time format:\n\n```bash\ncurl -X POST http://localhost:8090/fluree/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"from\": \"example/ledger\",\n    \"t\": \"PT5M\",\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\"\n    },\n    \"select\": {\"?person\": [\"*\"]},\n    \"where\": {\n      \"@id\": \"?person\",\n      \"@type\": \"schema:Person\"\n    }\n  }'\n```\n\nExpected output (same format as above, showing state from 5 minutes ago):\n```json\n[\n  {\n    \"@id\": \"ex:alice\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Alice Johnson\",\n    \"schema:email\": \"alice@newdomain.com\"\n  },\n  {\n    \"@id\": \"ex:bob\",\n    \"@type\": \"schema:Person\",\n    \"schema:name\": \"Bob Smith\",\n    \"schema:email\": \"bob@example.com\",\n    \"schema:knows\": {\"@id\": \"ex:alice\"}\n  }\n]\n```\n\n\n### History Query for a Specific Subject\n\nGet the history of changes for just `ex:alice` (optionally limit to a\nproperty with e.g. `[\"ex:alice\", \"schema:email\"]`):\n\n```bash\ncurl -X POST http://localhost:8090/fluree/history \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"from\": \"example/ledger\",\n    \"commit-details\": true,\n    \"history\": [\"ex:alice\"],\n    \"t\": {\"from\": 1},\n    \"@context\": {\n      \"schema\": \"http://schema.org/\",\n      \"ex\": \"http://example.org/\",\n      \"f\": \"https://ns.flur.ee/ledger#\"\n    }\n  }'\n```\n\nExpected output (showing only changes related to ex:alice):\n```json\n[\n  {\n    \"f:t\": 1,\n    \"f:assert\": [\n      {\n        \"@id\": \"ex:alice\",\n        \"@type\": \"schema:Person\",\n        \"schema:name\": \"Alice Johnson\",\n        \"schema:email\": \"alice@example.com\"\n      }\n    ],\n    \"f:retract\": [],\n    \"f:commit\": {\n      \"@id\": \"fluree:commit:sha256:...\",\n      \"f:address\": \"fluree:memory://...\",\n      \"f:alias\": \"example/ledger\",\n      \"f:branch\": \"main\",\n      \"f:previous\": null,\n      \"f:time\": 1704384000000,\n      \"f:v\": 1,\n      \"f:data\": {\n        \"@id\": \"fluree:db:sha256:...\",\n        \"f:address\": \"fluree:memory://...\",\n        \"f:assert\": [\n          {\n            \"@id\": \"ex:alice\",\n            \"@type\": \"schema:Person\",\n            \"schema:name\": \"Alice Johnson\",\n            \"schema:email\": \"alice@example.com\"\n          }\n        ],\n        \"f:retract\": [],\n        \"f:flakes\": 3,\n        \"f:size\": 384,\n        \"f:t\": 1\n      }\n    }\n  },\n  {\n    \"f:t\": 4,\n    \"f:assert\": [\n      {\n        \"@id\": \"ex:alice\",\n        \"schema:email\": \"alice@newdomain.com\"\n      }\n    ],\n    \"f:retract\": [\n      {\n        \"@id\": \"ex:alice\",\n        \"schema:email\": \"alice@example.com\"\n      }\n    ],\n    \"f:commit\": {\n      \"@id\": \"fluree:commit:sha256:...\",\n      \"f:address\": \"fluree:memory://...\",\n      \"f:alias\": \"example/ledger\",\n      \"f:branch\": \"main\",\n      \"f:previous\": {\"@id\": \"fluree:commit:sha256:...\"},\n      \"f:time\": 1704384120000,\n      \"f:v\": 1,\n      \"f:data\": {\n        \"@id\": \"fluree:db:sha256:...\",\n        \"f:address\": \"fluree:memory://...\",\n        \"f:assert\": [\n          {\n            \"@id\": \"ex:alice\",\n            \"schema:email\": \"alice@newdomain.com\"\n          }\n        ],\n        \"f:retract\": [\n          {\n            \"@id\": \"ex:alice\",\n            \"schema:email\": \"alice@example.com\"\n          }\n        ],\n        \"f:flakes\": 31,\n        \"f:size\": 4090,\n        \"f:t\": 4\n      }\n    }\n  },\n  {\n    \"f:t\": 5,\n    \"f:assert\": [\n      {\n        \"@id\": \"ex:alice\",\n        \"schema:age\": 43\n      }\n    ],\n    \"f:retract\": [],\n    \"f:commit\": {\n      \"@id\": \"fluree:commit:sha256:...\",\n      \"f:address\": \"fluree:memory://...\",\n      \"f:alias\": \"example/ledger\",\n      \"f:branch\": \"main\",\n      \"f:previous\": {\"@id\": \"fluree:commit:sha256:...\"},\n      \"f:time\": 1704384180000,\n      \"f:v\": 1,\n      \"f:data\": {\n        \"@id\": \"fluree:db:sha256:...\",\n        \"f:address\": \"fluree:memory://...\",\n        \"f:assert\": [\n          {\n            \"@id\": \"ex:alice\",\n            \"schema:age\": 43\n          }\n        ],\n        \"f:retract\": [],\n        \"f:flakes\": 32,\n        \"f:size\": 4120,\n        \"f:t\": 5\n      }\n    }\n  }\n]\n```\n\n## Usage\n\n### Settings\nConfiguration is handled through JSON-LD configuration files with samples (and\nthe default) located in the `resources/` directory. The server can be started\nwith different configuration files and profiles. \n\n#### Dynamic Configuration with ConfigurationValue\nFluree Server supports dynamic configuration values that can be resolved from\nJava system properties, environment variables, or default values. This allows\nyou to externalize configuration without modifying your JSON-LD files.\n\nTo use dynamic configuration, replace any configuration value with a\nConfigurationValue object:\n\n```json\n{\n  \"@type\": \"ConfigurationValue\",  // Optional - included for clarity\n  \"javaProp\": \"fluree.http.port\",\n  \"envVar\": \"FLUREE_HTTP_PORT\", \n  \"defaultVal\": 8090\n}\n```\n\nNote: The `@type` field is optional but recommended for clarity. At least one\nof `javaProp`, `envVar`, or `defaultVal` must be present.\n\n**Resolution Priority:**\n1. Java system property (highest priority)\n2. Environment variable \n3. Default value (lowest priority)\n\n**Examples:**\n\nSet HTTP port from environment variable with fallback:\n```json\n{\n  \"@id\": \"http\",\n  \"@type\": \"API\",\n  \"httpPort\": {\n    \"@type\": \"ConfigurationValue\",\n    \"envVar\": \"FLUREE_HTTP_PORT\",\n    \"defaultVal\": 8090\n  }\n}\n```\n\nConfigure cache size from Java property:\n```json\n{\n  \"@id\": \"connection\",\n  \"@type\": \"Connection\",\n  \"cacheMaxMb\": {\n    \"@type\": \"ConfigurationValue\",\n    \"javaProp\": \"fluree.cache.maxMb\",\n    \"envVar\": \"FLUREE_CACHE_MB\",\n    \"defaultVal\": 1000\n  }\n}\n```\n\nConfigure file storage path:\n```json\n{\n  \"@id\": \"storage\",\n  \"@type\": \"Storage\",\n  \"filePath\": {\n    \"@type\": \"ConfigurationValue\",\n    \"javaProp\": \"fluree.data.dir\",\n    \"envVar\": \"FLUREE_DATA_DIR\",\n    \"defaultVal\": \"/opt/fluree-server/data\"\n  }\n}\n```\n\n**Usage:**\n\nWith environment variables:\n```bash\nexport FLUREE_HTTP_PORT=9090\nexport FLUREE_CACHE_MB=2000\njava -jar target/fluree-server.jar\n```\n\nWith Java system properties:\n```bash\njava -Dfluree.http.port=9090 -Dfluree.cache.maxMb=2000 \\\n     -jar target/fluree-server.jar\n```\n\n**Note:** ConfigurationValue can be used for any configuration property that\naccepts a value. If no value can be resolved (no property set, no environment\nvariable, and no default), the server will fail to start with an error.\n\n#### Configuration Files\nSample configuration files are provided in the `resources/` directory:\n- `file-config.jsonld` - Default standalone server configuration with\n  file-based storage\n- `memory-config.jsonld` - Standalone server configuration with in-memory\n  storage\n- `config-raft.jsonld` - Raft consensus cluster configuration\n- `config-raft-standalone.jsonld` - Single-node Raft configuration for\n  development\n\n#### Starting the Server\nThe server can be started in different ways:\n- Default: Uses `file-config.jsonld` from resources\n- With specific config file: `-c` or `--config /path/to/config.jsonld`\n- With specific resource: `-r` or `--resource config-name.jsonld`\n- With config string: `-s` or `--string \"{config json}\"`\n- With profile: `-p` or `--profile dev` (applies profile-specific overrides)\n- Show help: `-h` or `--help`\n\n#### Configuration Options\nThe configuration files use the Fluree system vocabulary. Common configuration\nsettings include:\n\n**Storage Configuration:**\n- `filePath` - Directory path for file-based storage (e.g.,\n  \"/opt/fluree-server/data\" or \"dev/data\")\n- `@type: \"Storage\"` - Defines storage configuration (omit filePath for memory\n  storage)\n\n**Connection Configuration:**\n- `parallelism` - Number of parallel operations (default: 4)\n- `cacheMaxMb` - Maximum memory for caching in MB (default: 1000)\n- `commitStorage` - Reference to storage configuration for commits\n- `indexStorage` - Reference to storage configuration for indexes\n- `primaryPublisher` - Primary publisher configuration\n- `secondaryPublishers` - Optional array of secondary publishers\n- `defaults.indexing.reindexMinBytes` - Minimum bytes before reindexing\n  (default: 1000000)\n- `defaults.indexing.reindexMaxBytes` - Maximum bytes before reindexing\n  (default: 1000000000)\n\n**Consensus Configuration:**\n- `consensusProtocol` - Either \"standalone\" or \"raft\"\n- `maxPendingTxns` - Maximum pending transactions (standalone mode,\n  default: 512)\n\n**Raft-specific Configuration:**\n- `raftLogHistory` - Number of log entries to keep (default: 10)\n- `raftEntriesMax` - Maximum entries per batch (default: 200)\n- `raftCatchUpRounds` - Catch-up rounds for lagging nodes (default: 10)\n- `raftServers` - Array of server addresses in multi-address format (e.g.,\n  \"/ip4/127.0.0.1/tcp/62071\")\n- `raftThisServer` - This server's address from the raftServers list\n\n**HTTP API Configuration:**\n- `httpPort` - Port for HTTP API (default: 8090)\n- `maxTxnWaitMs` - Maximum transaction wait time in milliseconds\n  (default: 120000)\n- `closedMode` - Enable closed mode (requires authentication)\n- `rootIdentities` - Array of root identity DIDs for authentication\n\n#### Example Configuration\nHere's a minimal standalone server configuration:\n```json\n{\n  \"@context\": {\n    \"@base\": \"https://ns.flur.ee/config/main/\",\n    \"@vocab\": \"https://ns.flur.ee/system#\"\n  },\n  \"@id\": \"myServer\",\n  \"@graph\": [\n    {\n      \"@id\": \"storage\",\n      \"@type\": \"Storage\",\n      \"filePath\": \"/data/fluree\"\n    },\n    {\n      \"@id\": \"connection\",\n      \"@type\": \"Connection\",\n      \"cacheMaxMb\": 500,\n      \"commitStorage\": {\"@id\": \"storage\"},\n      \"indexStorage\": {\"@id\": \"storage\"}\n    },\n    {\n      \"@id\": \"consensus\",\n      \"@type\": \"Consensus\",\n      \"consensusProtocol\": \"standalone\",\n      \"connection\": {\"@id\": \"connection\"}\n    },\n    {\n      \"@id\": \"http\",\n      \"@type\": \"API\",\n      \"httpPort\": 8090\n    }\n  ]\n}\n```\n\n#### Profiles\nConfiguration files can include profiles that override base settings. For\nexample, a \"dev\" profile might use less memory and local file paths:\n```json\n\"profiles\": {\n  \"dev\": [\n    {\n      \"@id\": \"storage\",\n      \"filePath\": \"dev/data\"\n    },\n    {\n      \"@id\": \"connection\",\n      \"cacheMaxMb\": 200\n    }\n  ]\n}\n```\n\n### Network Architecture\n\n**Server Types:**\n- **Consensus nodes**: Process transactions and maintain ledger state. Minimum 3\n  for production (allows 1 failure).\n- **Query-only nodes**: Ephemeral servers for horizontal query scaling. Great\n  for containers and edge deployment.\n\n**Deployment Patterns:**\n- **Small**: 3 consensus nodes (handles 1 failure)\n- **Medium**: 3-5 consensus nodes + multiple query nodes\n- **Large**: 5+ consensus nodes (formula: `2f+1=n` where `f` = allowed\n  failures)\n\n**Best Practices:**\n- Route client traffic through query-only nodes\n- Keep consensus nodes in private networks\n- Query nodes forward transactions to consensus nodes using CQRS pattern\n- Query nodes cache data in-memory with LRU eviction\n\n## Development\n\n### Dependencies\n\nRun `make help` to see all available tasks.\n\n### Building\n\n- `make` or `make uberjar` - Build an executable server uberjar\n- `make docker-build` - Build the server Docker container\n- `make docker-push` - Build and publish the server Docker container\n\n### Running the Server\n\n#### Development Mode\n- `make run` - Run the server in development mode with the `dev` profile\n  - Uses reduced memory settings (200MB cache instead of 1000MB)\n  - Stores data in `dev/data` directory\n  - Reduces max pending transactions to 16\n  - Equivalent to: `clojure -M:run-dev`\n\n#### Production Mode\n- `make run-prod` - Run the server in production mode\n  - Uses default configuration from `file-config.jsonld`\n  - Full memory allocation (1000MB cache)\n  - Stores data in `/opt/fluree-server/data`\n  - Equivalent to: `clojure -M -m fluree.server`\n\n#### Running from JAR\nAfter building with `make uberjar`:\n```bash\njava -jar target/fluree-server.jar\n```\n\nWith options:\n```bash\n# With a specific profile (short or long form)\njava -jar target/fluree-server.jar -p dev\njava -jar target/fluree-server.jar --profile dev\n\n# With a custom config file\njava -jar target/fluree-server.jar -c /path/to/config.jsonld\njava -jar target/fluree-server.jar --config /path/to/config.jsonld\n\n# With inline configuration\njava -jar target/fluree-server.jar -s '{\"@context\": {...}}'\njava -jar target/fluree-server.jar --string '{\"@context\": {...}}'\n\n# With a resource from the classpath\njava -jar target/fluree-server.jar -r memory-config.jsonld\njava -jar target/fluree-server.jar --resource memory-config.jsonld\n\n# Show help\njava -jar target/fluree-server.jar -h\njava -jar target/fluree-server.jar --help\n```\n\n### Testing\n\n- `make test` - Run tests\n- `make benchmark` - Run performance benchmarks\n- `make pending-tests` or `make pt` - Run pending tests\n\n### Code linting\n\n- `bb lint` - Run both cljfmt and clj-kondo on the entire codebase\n- `bb fix` - Automatically fix formatting errors with cljfmt\n- `make clj-kondo-lint` - Run clj-kondo separately\n- `make cljfmt-check` - Check formatting with cljfmt\n- `make cljfmt-fix` - Fix formatting errors with cljfmt\n\n### Git hooks\n\n- `bb git-hooks install` - Set up a pre-commit git hook that checks your staged\n  changes with cljfmt and clj-kondo before allowing them to be committed","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluree%2Fserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluree%2Fserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluree%2Fserver/lists"}