1. Setting up AMQP with RabbitMQ and the ACF Plugin
AMQP support is reintroduced in the ACF Plugin version 1.8.0.2. This tutorial shows how to set up a local RabbitMQ broker in Docker, connect to it from FileMaker using the ACF Plugin, send a test message, receive it again, and try a persistent listener.
The setup is intended for development and testing. The same ideas can later be moved to a VPS or production server with proper users, firewall rules, monitoring, and backup routines.
- Setting up AMQP with RabbitMQ and the ACF Plugin
- What is AMQP?
- Why use a queue?
- Install a local RabbitMQ test broker
- Open the RabbitMQ web interface
- Initialize AMQP in FileMaker
- Send a message from FileMaker
- Receive one message from FileMaker
- Start a persistent listener
- Stop the persistent listener
- Send a message from the command line
- Web application producers
- Example use case: web shop orders
- Example use case: BOWC movement events
- Example use case: label printing station
- Performance testing
- Production notes
1.1. What is AMQP? ↑
AMQP means Advanced Message Queuing Protocol. It is a protocol for sending messages through a message broker. Instead of system A calling system B directly and waiting for the answer, system A can send a small message to a queue. A worker, listener, web app, FileMaker client, or background process can then pick up messages from that queue when it is ready.
RabbitMQ is one of the most widely used AMQP brokers. It is open source, mature, and has a useful web interface for monitoring queues, consumers, messages, exchanges, and bindings.
AMQP libraries exist for many environments, including:
- PHP
- Python
- Node.js
- Java
- .NET
- Go
- C and C++
- command-line tools
- FileMaker, now through the ACF Plugin
This makes AMQP a practical bridge between FileMaker and web solutions. A FileMaker solution can send a message to a web worker. A web shop can send a message to FileMaker. A packing station can listen for label print jobs. The important point is that the systems do not need to do all the work at the exact same time.
1.2. Why use a queue? ↑
Direct integrations are simple, but they can become slow when many events happen at once.
For example, imagine a FileMaker script that calls a web API every time a record is updated. If 100 records are updated in a short time, FileMaker may wait for 100 web requests. The user interface can feel slow, and FileMaker Server or the web server can be overloaded.
With AMQP, the FileMaker script can instead send 100 small messages quickly. RabbitMQ stores them in a queue. One or more workers then process the messages at a controlled pace.
This is useful for:
- keeping a web shop in sync with FileMaker
- notifying FileMaker when new web orders arrive
- moving heavy work out of user-facing scripts
- sending label print jobs to a packing-line FileMaker client
- collecting many browser events and letting FileMaker process them later
- making integrations more robust when the receiver is temporarily busy
1.3. Install a local RabbitMQ test broker ↑
This tutorial assumes that you have a local RabbitMQ broker running in Docker.
For a complete Docker setup, including the Dockerfile, docker-compose.yml, RabbitMQ configuration, enabled plugin list, and predefined queue/exchange definitions, see Installing RabbitMQ broker using Docker
That article creates a development broker with these settings:
| Service | Address |
|---|---|
| AMQP broker | localhost:5672 |
| RabbitMQ management web UI | https://localhost:15672 |
| User | acf |
| Password | acf_dev_password |
| Virtual host | / |
The predefined topology includes direct exchanges and queues named:
celeryacf-test
The celery queue and exchange match the historical defaults used by the AMQP functions.
1.4. Open the RabbitMQ web interface ↑
Open:
https://localhost:15672
Login:
User: acf
Password: acf_dev_password
The management interface is useful for checking:
- queues
- number of ready messages
- number of consumers
- exchanges
- bindings
- publish and consume rates
- connections and channels


1.5. Initialize AMQP in FileMaker ↑
In FileMaker, initialize the ACF Plugin AMQP settings:
Set Variable [ $$AMQP ; ACF_AMQP_Initialize ( "127.0.0.1" ; "acf" ; "acf_dev_password" ; "5672" ) ]
Expected result:
Broker: amqp://acf:**@127.0.0.1:5672//
ACF_AMQP_Initialize stores the connection settings used by the send and listen functions. It does not keep a permanent sending connection open.
Parameters:
| Parameter | Description |
|---|---|
broker |
RabbitMQ host name or IP address. For the local Docker broker, use 127.0.0.1. |
user |
RabbitMQ user name. |
password |
RabbitMQ password. |
port |
AMQP port, normally 5672. |
1.6. Send a message from FileMaker ↑
Send a simple test message to the celery exchange and queue:
Set Variable [ $$AMRes ;
ACF_AMQP_Send (
"acf.test.echo" ;
"client1¶Order¶12345¶manual test" ;
"celery" ;
"celery" ;
1 ;
1
)
]
Expected result:
OK
Parameters:
| Parameter | Description |
|---|---|
functionName |
A task or message name. For example acf.test.echo, order.created, or label.print. |
parameterList |
A carriage-return separated list of values. In FileMaker this is normally built with ¶. |
Queue |
AMQP exchange name. In the local test setup, celery exists by default. |
routingKey |
Routing key. For this test, use celery. |
QueueType |
Compatibility parameter. Use 1 for the normal durable test setup. |
recipientType |
Compatibility parameter. Use 1 for the current Celery-style message format. |
After sending, open the RabbitMQ management UI and look at the celery queue. If no listener has consumed the message yet, the queue should show one ready message.
Picture placeholder:
[Insert screenshot: celery queue with ready message count]
1.7. Receive one message from FileMaker ↑
To receive a single message and return it to FileMaker:
Set Variable [ $$AMQP_Listen ;
ACF_AMQP_Listen ( "celery" ; 1 ; "" ; 5 )
]
Expected result:
acf.test.echo
f3eb5af0-8e2f-45bd-8c30-82ab3f2d86a1
client1
Order
12345
manual test
The second line is the message id. It will be different for each message.
Parameters:
| Parameter | Description |
|---|---|
Queue |
Queue name to consume from. |
QueueType |
1 declares a durable queue and exchange. |
fmScript |
Empty string means the function returns one message instead of calling a script. |
timeout |
Number of seconds to wait for a message. |
1.8. Start a persistent listener ↑
The listener can also call a FileMaker script when a message arrives.
Example:
Set Variable [ $$AMQP_Listen ;
ACF_AMQP_Listen ( "labelPrint" ; 1 ; "Handle label print message" ; 0 )
]
With a script name and timeout = 0, the plugin starts a persistent listener. The listener is polled during FileMaker idle time. When a message arrives, the plugin calls the named FileMaker script and passes the message as the script parameter.
The script parameter has this shape:
task
message-id
arg1
arg2
arg3
...
For a label-printing workstation, a message might contain:
label.print
message-id
ORDER-12345
SKU-987
2
The FileMaker script can parse the lines and print the labels on the local USB label printer.
Important: the current listener acknowledges the message after it starts the FileMaker script, not after the script has finished printing or processing. For critical workflows, consider adding your own job id and status table so repeated or failed jobs can be detected.
1.9. Stop the persistent listener ↑
Stop the listener:
Set Variable [ $res ; ACF_AMQP_Close() ]
The persistent listener records which FileMaker file started it. If several FileMaker files are open in the same client, the plugin uses this ownership information to avoid calling a script in the wrong file.
Use ACF_AMQP_Close() in shutdown scripts or before changing queue configuration.
1.10. Send a message from the command line ↑
You can also publish messages from the RabbitMQ container using rabbitmqadmin.
Publish to the acf-test exchange and queue:
docker exec acf-rabbitmq rabbitmqadmin publish \
--username=acf --password=acf_dev_password --vhost=/ \
exchange=acf-test routing_key=acf-test \
payload='{"id":"manual","task":"acf.test","args":["hello"]}'
Get one message from the celery queue:
docker exec acf-rabbitmq rabbitmqadmin \
--username=acf --password=acf_dev_password --vhost=/ \
get queue=celery requeue=false
List queues:
docker exec acf-rabbitmq rabbitmqctl list_queues name messages consumers
List exchanges:
docker exec acf-rabbitmq rabbitmqctl list_exchanges name type durable
1.11. Web application producers ↑
AMQP is commonly used from web applications. A PHP web shop, for example, can publish a message when a new order is created. FileMaker can then listen to a queue and process the order.
PHP does not include AMQP as a standard built-in feature, but there are good options:
| PHP option | Notes |
|---|---|
php-amqp extension |
Native extension, usually backed by rabbitmq-c. Good when you control the server packages. |
php-amqplib/php-amqplib |
Pure PHP Composer package. Often easier to deploy in web applications and containers. |
On a VPS, either option is possible. On shared hosting, the pure PHP library may work if outbound socket connections to RabbitMQ are allowed. If the shared host blocks port 5672, a small HTTPS endpoint on a VPS can receive the web request and publish to RabbitMQ.
1.12. Example use case: web shop orders ↑
- A customer places an order in the web shop.
- The web shop publishes an AMQP message with order id and shop id.
- RabbitMQ stores the message in a queue.
- A FileMaker client or server-side process listens to the queue.
- FileMaker receives the message and runs an order import script.
- The script pulls the order details from the web shop API or database.
This avoids making FileMaker poll the web shop every few seconds. It also avoids forcing the web shop to wait while FileMaker processes the order.
1.13. Example use case: BOWC movement events ↑
In a browser interface where users move many blocks or objects, calling a FileMaker script on every small movement can create lag.
With AMQP:
- The web interface sends movement messages to RabbitMQ.
- FileMaker listens to a queue.
- FileMaker processes the moves when idle or at a controlled pace.
This lets the browser UI stay responsive while FileMaker still receives the movements.
1.14. Example use case: label printing station ↑
A FileMaker client at a packing line can have a USB label printer connected.
The packing-line client starts a listener on a queue such as:
labelPrint
Other systems can send print jobs to that queue. The FileMaker client receives the message, parses the job, and prints locally.
This is a good fit because the label printer is physically attached to one workstation, while the print requests may come from several users or from the web shop.
1.15. Performance testing ↑
For a quick local test, send 100 messages in a loop from FileMaker:
Set Variable [ $i ; 1 ]
Set Variable [ $$p1 ; ACF_GetDuration_uSec ]
Loop
Exit Loop If [ $i > 100 ]
Set Variable [ $$AMRes ;
ACF_AMQP_Send (
"acf.test.echo" ;
"client1¶Order¶12345¶manual test " & $i ;
"celery" ;
"celery" ;
1 ;
1
)
]
Set Variable [ $i ; $i + 1 ]
End Loop
Set Variable [ $$p2 ; ACF_GetDuration_uSec - $$p1 ]
In one local development test, 100 messages were sent in about 555,380 microseconds, or about 5.5 ms per send. The exact number will vary by machine, broker location, Docker performance, network, and whether RabbitMQ is local or remote.
Here is a screenshot after sending 100 messages. Then in the script handling the messages, I added a Pause/Resume Script [ Duration seconds: 1 ] so that I could take the screenshot below while it was consuming the messages.

Useful things to measure:
- time to publish 100 messages
- time to consume 100 messages - This depends on the task assigned to the process.
- queue depth while the listener is stopped
- queue depth while the listener is running
- RabbitMQ publish rate
- RabbitMQ deliver/ack rate
1.16. Production notes ↑
The Docker setup in this article is for local development.
For production:
- create dedicated RabbitMQ users
- use strong passwords
- restrict firewall access to the AMQP port
- avoid exposing the management UI publicly
- consider TLS/AMQPS for remote connections
- monitor queue depth and consumer count
- use meaningful queue names per workflow
- include a unique job id in important messages
- design scripts so repeated messages can be handled safely
AMQP gives FileMaker and web systems a clean way to communicate without forcing every task to happen immediately. RabbitMQ absorbs the bursts, workers process at their own pace, and FileMaker can become part of a larger event-driven system.
