When one HAPI FHIR server should serve several organizations
HAPI FHIR JPA partitioning is the documented feature for serving several organizations or data sources from one FHIR endpoint. Each resource is placed in a partition, and partitions can be used for multitenancy, for separating data sources, or for grouping data by region. For a health network, state agency, or platform team, the decision is less about whether the feature works and more about whether one shared server matches how your organizations are governed. Settle that question before any configuration begins, because it determines who operates the server, who approves changes, and who answers for a data incident.
A single shared server is a sound choice when the participating organizations accept the same operator, the same release calendar, and the same baseline of access controls. It also fits when the data sources are similar enough that one set of validation, terminology, and search settings serves all of them, and when a central team needs to report across partitions. Illustrative example: a state agency that receives immunization feeds from several clinics under one data-sharing agreement may fit this pattern well. A set of unrelated vendors, each with its own change windows and audit requirements, may not.
Separate deployments may be easier to govern when one organization's data must never share a database instance with another's, when a contract or regulator requires independent backup, restore, or retention schedules, or when each party needs its own upgrade timing and outage tolerance. Separate deployments also cost more to run, since each one carries its own database, patching, monitoring, and backups. Put that cost next to the governance benefit in the decision. Ask your compliance and legal owners whether a logical partition gives enough isolation for the obligations you carry, and get that answer in writing.
A partition is a logical boundary inside one application and one database, so security, operations, and limits must be confirmed for your own setup. HAPI FHIR does not provide a single security layer. You assemble authentication, authorization, consent, and audit from its building blocks. This page covers configuration, setup, security, and the documented limits, including search and history behavior. Before you commit, confirm those limits against the version you plan to run and test them with data shaped like your real workloads.
Partitioning options and when each one fits
This table compares four common ways to divide one shared HAPI FHIR JPA server, or to avoid sharing one. Read each row against how the data is owned, reported and governed, since ownership usually decides the split more than the technology does. Confirm exact partition identifiers, access rules and search and history limits in the HAPI FHIR partitioning documentation before you commit.
| Option | Isolation and governance | Effect on administration and search | When it fits |
|---|---|---|---|
| One partition per tenant organization | Data is separated by organization. Governance needs a named owner per organization and access rules that map each user to its partition. | One server to run and upgrade. Cross-organization searches and reports need explicit design, so confirm the documented behavior. | Several organizations share one platform and each needs its records kept apart. |
| One partition per source system | Separates feeds such as an EHR and a laboratory system. Governance follows the system owner, who may not own the patient relationship. | Easy to trace where each record came from. A patient present in several sources sits in several partitions, so matching needs a plan such as MDM. | Data is owned and reported per source, and each source has its own retention or access rules. |
| One partition per region | Supports residency or regional stewardship. Governance needs rules for records that cross regions, such as a patient who moves. | Regional administrators can be scoped to their own data. Queries spanning regions need a defined approach and extra design effort. | Data residency requirements or a regional operating model drive the split, and regional teams manage their own data. |
| Separate server per tenant | Strongest separation of data, configuration and credentials. Each server needs its own access reviews, patching and backup process. | Highest administration cost, since every server is upgraded, monitored and backed up. Search stays fully inside each tenant. | A tenant needs isolation a shared database cannot meet, or it requires its own release schedule. |
How partitioning assigns each resource to a partition
HAPI FHIR JPA partitioning places each stored resource in a partition, and the partition becomes the unit that groups data. A partition can stand for a tenant, an organization using the server, a source system feeding it, or a geographic region. Once a resource is written, its partition determines which requests can see it, so the assignment is a design decision to settle before any data is loaded. The request side matters too. Tenant identification in the URL and the partition interceptors that act on each request must map to the same partition scheme that your loaders use. Confirm the exact mechanism in the partitioning documentation for your HAPI FHIR version, because the version determines which features apply and how they behave.
Before loading data, the team needs to decide three things. The first is the partition key: which attribute of the incoming data sets the partition, such as a source system code, an organization identifier or a region code. The key should be stable over time, because a value that changes after records are written usually means moving those records between partitions. The second is how existing resources without a partition will be handled. Records from a legacy export or a bulk load may arrive without the value the key depends on, and the server needs a rule for them. Some resources may be forced into a default partition. Confirm how your version assigns that default and whether it can be overridden before you run the first import.
The third decision is how references between resources in different partitions will be treated. A clinical resource in one partition may point to a patient or practitioner held in another, for example when an organization shares reference data across tenants. Decide whether those references are allowed, whether they resolve within the requesting partition, and what a client receives when the target is not visible to it. Test this with representative records from each source, including a case where the referenced resource is absent from the requesting partition. Confirm the cross-partition reference behavior in the documentation for your version before you design client applications around it.
Write the answers down as a partition map before any load job runs. The map should list the partition key, the handling rule for unassigned records, the reference policy and the partition each request path resolves to. Include the search and history limits documented for partitioned data, since those limits decide what each tenant or source can report on. Ask the vendor or community channel to confirm any behavior you cannot find in the documentation for your version, and record the answer alongside the map. A reviewed map gives your security, data governance and operations teams one document to check against the server configuration and the test results.
Setting up partitioning on a HAPI FHIR JPA server
This sequence takes a HAPI FHIR JPA server from a version and database choice to a verified partitioned deployment. Each step ends with a check, so the team can confirm that tenant data stays separated before any real patient or customer data is loaded.
Confirm the JDK and HAPI FHIR version pairing
The platform team pins the HAPI FHIR release and its matching JDK before anything else is installed. HAPI FHIR 8.2.0 requires JDK 17, and the current release line includes v8.8.2, released on 25 September 2026. Confirm the JDK requirement for the exact version you choose in the HAPI FHIR versions documentation, then record both values in your build and deployment configuration. The step is done when a test build of the starter runs on the pinned JDK without errors.
Choose PostgreSQL or Microsoft SQL Server
The database owner selects a production database before configuration begins. The JPA server starter defaults to an embedded H2 database, which suits local testing only. The starter supports PostgreSQL and Microsoft SQL Server for production, and MySQL is not supported. Confirm the database version against the starter's documentation, provision an empty schema, and check that the server can connect with a dedicated service account. The step is done when the starter starts against the new database and creates its schema.
Enable partitioning in the starter configuration
The platform engineer switches partitioning on in the starter's configuration and points it at the production database. Use the partitioning settings described in the HAPI FHIR JPA partitioning documentation for your version, because property names change between releases. Keep the default partition in place, since resources that cannot be assigned to a tenant are placed there. The step is done when the server restarts with partitioning enabled and the capability statement loads without errors.
Define the partition scheme and tenant identifiers
The solution architect and data owners agree on how partitions map to organizations, data sources or regions, and which identifier names each one. The scheme should be written down with one identifier per partition, the rule for how the identifier appears in the request URL, and who approves new tenants. Confirm the partition identifier rules in the partitioning documentation before creating partitions. The step is done when the scheme document is approved and the first two partitions exist in the database.
Register the partition interceptors
The platform engineer registers the partition interceptors that read the tenant identifier from each request and apply it to reads and writes. Interceptor registration is set in the server configuration and must match the partition scheme from the previous step. Confirm the interceptor names and their order for your HAPI FHIR version in the partitioning documentation. The step is done when a create request sent to a tenant URL is stored under that tenant's partition and the server log shows no interceptor errors.
Load test data into two partitions
The data team loads synthetic test resources into two separate partitions so that isolation can be tested with real request paths. Use fictional patients and practitioners, and record which partition each resource was written to. Keep the load small and repeatable so that the same dataset can be reloaded after configuration changes. The step is done when both partitions contain the expected resource counts and the records can be read back through their own tenant URLs.
Verify that partitions stay isolated
The security engineer runs cross-partition search and read tests to confirm that data does not leak between tenants. Write a resource to partition A, then search for it through partition B and confirm that it is not returned. Repeat the test for reads by identifier, history and each resource type in use. Document the search and history limits that the partitioning documentation describes, so that the operations team knows what the platform does not guarantee. The step is done when every cross-partition test returns no foreign data and the results are saved as evidence.
How tenant identification in the URL routes requests
In a partitioned HAPI FHIR JPA server, the tenant is identified by a segment in the request URL, and that segment decides which partition each read and write uses. Before you build anything, confirm the exact URL pattern in the HAPI FHIR documentation for the version you run, including where the tenant segment sits relative to the FHIR base path and the resource type. Also confirm whether the server offers any header-based alternative for tenant selection and how it behaves when a URL segment and a header disagree. Those two points determine every client integration, so settle them in writing with your platform team before the first client is configured.
The server's behavior when the tenant segment is missing or unknown needs explicit testing. Send requests without a tenant segment, with a tenant name that has never been registered, and with a name that differs only by case or by a trailing character. For each case, record the HTTP status, whether a resource was created, and which partition it landed in. Confirm in the documentation whether unidentified requests fall back to the default partition. If they do, a misconfigured client can write clinical data outside its tenant, so plan alerts on writes to the default partition and decide who reviews them. Do not assume the behavior is the same across versions without checking your own test results.
Naming conventions for tenants are a governance decision, not a technical afterthought. Tenant identifiers appear in URLs, access logs, audit records and client configuration, so choose short, lowercase, stable identifiers that do not encode personal data, organization names that may change after a merger, or environment labels that could be confused across dev and production. Keep one authoritative registry that maps each identifier to its partition configuration and to the owning organization. Reserve names that the server or your own tooling uses, and agree on who may add a tenant, because each new tenant changes the routing surface that every gateway and client depends on.
Client applications must be configured with a base URL that already contains the correct tenant segment, so that a developer never assembles tenant paths by hand. Store that base URL as configuration per environment and per tenant, and review it as part of release. Gateways and reverse proxies in front of the server must preserve the path segment exactly: check that no prefix-stripping or path-rewrite rule removes or reorders it, and that the gateway does not forward a request from one tenant's client under another tenant's segment. Bind authorization to the tenant as well, so that a token valid for one tenant cannot read another. Ask your gateway team to supply a test matrix covering each tenant, each client and the missing-segment cases.
Keeping one tenant's data out of another tenant's requests
Partitions separate where data is stored and how requests are routed, but they do not decide who may read which tenant. The cards below cover the access rules, audit trail, administrator reach, credentials and backup scope that a team must design alongside partitioning.
Partitions do not enforce access
A partition places resources in a separate logical space, but it does not by itself decide which caller may read or write a tenant's data. HAPI FHIR states it does not provide one security layer for every case and offers building blocks instead. Define an explicit access rule for each tenant, and test that a token issued for one tenant is refused on every other tenant's endpoints and search requests.
Choosing the authorization building blocks
Map each tenant's rules onto the supplied components: an authentication interceptor to validate tokens, the AuthorizationInterceptor to grant or deny operations by resource type and compartment, and consent or search narrowing interceptors where patients or data sources need finer limits. Document which component enforces each rule so reviewers can trace a decision to code or configuration.
Narrowing search and cross-tenant references
Search and history results must stay inside the caller's partition, and references between resources must not let a request reach another tenant's records. Test queries with reference parameters, _include and history calls that point at identifiers from a different tenant. Confirm the documented search and history limits for partitioned servers before promising isolation to a tenant.
Audit logging for each tenant
BALP audit logging records access events, and in a shared server each event should be attributable to a tenant, a caller and a resource. Confirm which fields the audit output carries, where it is stored, and whether one tenant's auditors can query only their own events. Plan retention and export per tenant so an investigation does not expose another tenant's activity.
Administrator access across partitions
Server administrators and platform engineers often hold rights that reach every partition, including the database and configuration. Decide who holds those rights, how they are granted and revoked, and whether their actions are logged separately. Establish a break-glass procedure and review administrator access on a fixed schedule, since one account with broad reach affects every tenant.
Key and database credential handling
Each tenant's client credentials, signing keys and interceptor secrets need an owner, a rotation process and a storage location outside application configuration files. Because all partitions share one database, the server's database credential reaches every tenant's rows. Ask who can read that credential, how it is rotated without downtime, and whether tenant-specific keys are kept separate from it.
Backup and restore across tenants
A backup of the shared database contains every partition, so restoring one tenant's data alone is not a simple operation. Confirm with the database vendor and your own tooling whether a single-tenant restore is possible, and test it on a copy. Define who may request a restore, how the other tenants are protected during it, and how restored data is checked against the audit trail.
Resources in the default partition and documented search and history limits
Decide first which resource types are allowed to live in the default partition, because a resource written without a clear partition context can end up there. Shared reference data such as CodeSystem, ValueSet and StructureDefinition resources is the usual reason to keep content in the default partition, since every tenant needs to read the same terminology and conformance content. The risk is the reverse case: tenant-specific data written by a client that omits or mis-sets the tenant identifier may land in the default partition, where other tenants can find it. Confirm in the HAPI FHIR partitioning documentation for your version which requests write to the default partition when no partition is given, and write that behavior down as a design rule.
Shared reference data also needs an owner. Changes to a CodeSystem or ValueSet in the default partition affect every tenant that uses it, so the team should define who can create or update these resources, how changes are reviewed, and how a bad update is reverted. Limit write access to the default partition at the authorization layer, not only in client documentation. HAPI FHIR does not supply one complete security layer, so the AuthorizationInterceptor or your own gateway rules must enforce the restriction. Test it with a tenant credential that attempts to write a reference resource and confirm that the write is refused.
Search is the first behavior to review. Confirm whether a search made with a tenant identifier in the URL returns only that partition's resources, whether it also returns default partition resources, and what a search without any tenant identifier returns. Each answer changes what a client can see, so record the result for each resource type your tenants query. Also check how _include and _revinclude behave across the partition boundary, because an included resource may come from a partition the requester is not meant to read.
History and cross-partition references need the same review. Confirm how instance, type and server-level history are returned for a tenant, including whether shared default partition resources appear in a tenant's history feed and how deleted resources are reported. Then test whether a tenant Patient that references a default partition Organization or CodeSystem resolves correctly, and whether a reference to a resource in another tenant's partition resolves at all or fails. These results determine whether reference data can be shared without leaking tenant detail.
Treat all of these behaviors as version-specific. Build a test matrix from your own query patterns, covering each resource type, search parameter, include, history call and reference pattern your applications use, and run it against the exact HAPI FHIR version and database you plan to operate. Record the expected and actual results, and repeat the matrix before each upgrade. If the documentation for your version leaves a case unclear, ask the vendor or support provider to confirm it in writing before the design is committed.
Limits to confirm in your environment before you commit
Partitioning changes how search, history, reporting and data movement behave across tenants, so several limits cannot be taken from a feature list. Each card names one item to verify, and the check to run with the vendor, the documentation for your exact release, or a proof-of-concept test on your own database.
Search and history limits for your release
The partitioning documentation describes how search and history behave across partitions, but the details depend on the version you deploy. Read the partitioning page for the exact release in your plan, list every search parameter and history operation your applications use, and confirm each one is supported with partitions enabled. Record the answers in writing before you size the design.
Performance with many partitions
Partition count and tenant size both affect query plans, index use and migration runtime, and no supplied benchmark covers your workload. Build a proof of concept with the number of partitions you expect at year three, load a large tenant alongside small ones, and measure search latency and write throughput. Ask the vendor which partition counts they have tested and under what conditions.
Effect of the database engine
The JPA server runs on PostgreSQL or Microsoft SQL Server for production and does not support MySQL, so the engine you choose is part of the partitioning design. Confirm how partition keys, indexes and constraints map to your chosen engine, and test backup, restore and failover with partitioned data. Check the engine version support in the release documentation before you commit.
Reporting and bulk export across partitions
Cross-tenant reports, aggregate queries and bulk export are where partition boundaries most often surprise teams. Write down each report and export your organization needs, including whether it must span tenants, and test it against a partitioned dataset. Confirm whether the access controls you apply to a tenant also apply to bulk operations, and who owns the export output.
Moving data between partitions later
Moving a patient or a data source from one partition to another after go-live is a different task from initial loading. Ask the vendor and the documentation whether resource moves between partitions are supported, what references and history they affect, and how long a move takes at your data volume. Run a rehearsal on a copy before you promise a tenant that consolidation or separation is possible.
Commercial support and the evaluation server
The HAPI FHIR README points to Smile CDR for commercial support, and the public demonstration server at hapi.fhir.org is for evaluation only. Do not load organizational or patient data there. Ask whether your support model needs a commercial agreement, confirm what that agreement covers for partitioning, and plan your own test environment inside infrastructure you control.
Questions buyers ask before hiring help with HAPI FHIR partitioning
What drives the cost and effort of HAPI FHIR partitioning?
The main drivers are the partition design, the number of data sources or tenants, the security model, the database choice and the amount of existing data that must be moved or tested. A design with a few partitions that share one access policy is a different job from one with many organizations, each with its own consent rules and reporting needs. Partitioning is a one-time design and build effort, while hosting, backups, upgrades and access reviews recur. Ask any partner to price each of these drivers separately in the written scope so you can see which ones move the number.
Cost drivers to ask about:
- Partition design and tenant identification in the URL
- Number of sources and how much data each brings
- Authorization rules and interceptors you need to build
- Testing and migration of existing data
Can our team configure HAPI FHIR partitioning on its own?
Yes, a team with Java, Spring Boot and FHIR experience can configure partitioning from the HAPI FHIR documentation, and many do. The harder part is usually not the configuration but the decisions around it: which resources are forced into the default partition, how search and history behave across partitions, and how access is enforced. HAPI FHIR does not provide a single one-size-fits-all security layer, so you will assemble authentication, authorization and audit pieces yourselves. If your team has not run a production JPA server before, a partner can review the design before you commit to it.
How long does HAPI FHIR partitioning work take?
Duration depends mostly on your environment and how many decisions are still open when the work starts. Timing is set by the number of partitions, the readiness of your identity and infrastructure, the state of your existing data, and how many people must approve access policy. Engagements are normally fixed-scope, so the timeline is agreed in writing before work begins. We do not publish durations in advance. Ask for a timeline that lists each dependency, such as access to your database and identity provider, and who must sign off each stage.
What do you need from our organization during the engagement?
You will need named data owners who can decide which records belong to which partition and who may see them. Your security or compliance lead must make access policy decisions, including who administers partitions and how exceptions are handled. We also need representative test data, ideally with realistic record shapes but no live patient data, and access to your non-production infrastructure, database and identity provider. Without these, the design stays theoretical and testing slips. Agree these responsibilities in the scope so each party knows what it owes.
Does partitioning limit search or history across organizations?
Yes, you should plan for it. The HAPI FHIR JPA partitioning documentation describes search and history behavior that differs from a single shared store, so queries that cross partitions may not work the way clients expect. Check how your consumers search before the design is fixed, and test those exact queries against your partition layout. A partner can document the limits your clients will meet so that application teams are not surprised after go-live.
Which database should we use with HAPI FHIR partitioning?
HAPI FHIR's JPA server starter defaults to an embedded H2 database, which is suited to evaluation rather than production. For production, the starter supports PostgreSQL and Microsoft SQL Server, and it does not support MySQL. Your choice should follow your existing database standards, your backup and recovery capabilities, and your operations team's experience. Confirm the supported versions for the HAPI FHIR release you plan to use before you build, since the required JDK and database versions change between releases.
Does DeployOpen publish a price for HAPI FHIR partitioning?
No. DeployOpen does not publish a price list. A quote follows from a written scope that lists the partition design, sources, security model, database, testing and data migration, along with the deliverables and dependencies on your side. Most engagements are fixed-scope, so you can compare proposals line by line. Ask each partner to state which costs are one-time and which recur, such as hosting, upgrades and support, and what would change the quote if the scope grows.
How DeployOpen scopes and delivers HAPI FHIR partitioning
DeployOpen plans, builds and documents HAPI FHIR partitioning inside infrastructure you control, so several organizations or data sources can share one JPA server with boundaries that are written down and testable. Each engagement starts with a written scope that names the tenants, the partition model and the search and history limits your users will accept. Engagements are fixed-scope, and ongoing support is available as a retainer.
How we scope
- The written scope lists each tenant or data source and the partition it will occupy on the server.
- Tenant identification in the URL, partition interceptors and the default partition are agreed before any build work starts.
- Search and history limits that partitioning imposes are written down so clients and data owners know them up front.
How we build
- Partition routing is configured on the JPA server, with the interceptors that assign tenant context to each request.
- Resources that must not belong to a tenant are forced into the default partition under a documented rule.
- Authorization, consent and audit controls are layered on with HAPI's building blocks, since HAPI provides no single security layer.
How we hand over
- Documentation covers the tenant model, partition rules, interceptor configuration and the search and history limits.
- Isolation tests, covering cross-tenant reads and writes, are run against the agreed scope and the results delivered.
- Your team receives runbooks for onboarding a new tenant and for checking partition configuration after a server upgrade.
How we support
- Ongoing support is available as a retainer covering upgrades, configuration reviews and tenant onboarding requests.
- Upgrades are planned against the HAPI FHIR release line and its required JDK version, confirmed for each target release.
- Periodic reviews confirm that tenant boundaries, interceptor settings and access rules still match the agreed scope.

