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.

  1. Setting up AMQP with RabbitMQ and the ACF Plugin
    1. What is AMQP?
    2. Why use a queue?
    3. Install a local RabbitMQ test broker
    4. Open the RabbitMQ web interface
    5. Initialize AMQP in FileMaker
    6. Send a message from FileMaker
    7. Receive one message from FileMaker
    8. Start a persistent listener
    9. Stop the persistent listener
    10. Send a message from the command line
    11. Web application producers
    12. Example use case: web shop orders
    13. Example use case: BOWC movement events
    14. Example use case: label printing station
    15. Performance testing
    16. 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:

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:

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:

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:

RabbitMQ-overview

RabbitMQ-Queues

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

  1. A customer places an order in the web shop.
  2. The web shop publishes an AMQP message with order id and shop id.
  3. RabbitMQ stores the message in a queue.
  4. A FileMaker client or server-side process listens to the queue.
  5. FileMaker receives the message and runs an order import script.
  6. 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:

  1. The web interface sends movement messages to RabbitMQ.
  2. FileMaker listens to a queue.
  3. 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.

AfterSending100Messages

Useful things to measure:

1.16. Production notes

The Docker setup in this article is for local development.

For production:

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.