I publish data Actors on the Apify Store as Yappman Data, all on pay-per-event pricing. This is a list of things I got wrong about pricing and charging, and what I did about each. It is not a recipe. It is the short version of my own notes, in case it saves you the same detours.
1. I thought tier-priced events were not charged
My early notes said every event on our Actors was flat, and that version 4.0.2 of the Python SDK bills nothing on tier-priced events. If that were true, our main per-row events would have billed $0.
It was wrong. On 13 Oct our UK Actor session checked run metadata from an owner run. The tiered product event had been resolved to a flat price of a few tenths of a cent, and the run's charged-event count showed the events had been billed. The platform turns each tier into one flat price for the caller's plan before the run starts. The SDK only skips an event if the run's pricing info still carries tiers, and it never does.
What I changed: I corrected the notes, which had been wrong about the impact, and kept the main per-row events tiered as designed. On the UK grocery Actor the product event is $0.0025 on the Free plan down to $0.0015 on Gold. The basket and Standby events and the start fee stay flat, by choice.
The lesson is to read the numbers on a real run instead of trusting what you remember about the SDK.
2. My own test runs were being cut short
The platform clamps each run's maximum charge to the remaining monthly usage limit of the account that starts it. That affects you when you run your own Actor for snapshots, canaries and tests. Those runs were being truncated.
What I changed: owner-account runs now skip charge calls. That shipped in UK 0.2.21, AU 0.1.12 and hotels 0.1.25. The gate is the Actor owner's user id, so anything run with the owner's token is free and must never be used to serve paying users. Two things to remember: platform usage from those runs still counts towards the limit, and the limit only stops runs started from your own account. Other people's runs of a public Actor are billed to them.
3. Charged-event counts after a restart
I saw cases where charged-event counts and the run's maximum charge did not behave as I expected after a platform reboot of a run. I collected evidence from test runs and reported it as an issue on the SDK's GitHub repo. Apify closed it as completed on 3 November.
I did not wait for a platform fix. I approved an in-Actor spend limit: before each batch of rows is pushed to the dataset, the Actor cuts the batch to the number of rows that still fit under the run's maximum charge, after the start fee and the rows already pushed. After a restart it works out "rows already pushed" from the run's own dataset. The Property Actor's README states the result: a restarted run does not charge the run start or any row twice, and stays within your maximum charge.
The lesson is not to rely on the platform alone to enforce a cap. Enforce it in the Actor too, and test it with a simulated restart.
4. Price increases are the locked direction
The Console allows one price increase per Actor per month. Decreases and removals are not locked. A new paid event on a public Actor counts as an increase and needs 14 days' notice.
Two things followed from that.
- Dates slip. I planned two new add-on events on the UK Actor,
product-detailat $0.005 andprice-historyat $0.004, to be chargeable around 26 Oct. After the notice and the monthly rule they could not go in before 28 Oct, so the start moved later. Pricing for those events is announced in advance, and charging starts only when the code that enables them is released. - Transfer cost belongs in the price. I raised the buyer-profile event on our Contracts Actor from $0.05 to $0.10 per decision on 12 Oct, because one run pulls 365 daily files of 150 to 450 MB and the transfer cost is real. The event started charging $0.10 on 26 Oct.
My own rule now: pricing is never done in a hurry.
5. I priced above what the free source justifies
LEI Lookup started at $0.004 per entity. On 23 Oct I set it to $0.001 per entity ($1.00 per 1,000), with no start fee. My reasoning in the notes: LEI data is CC0 and free at source, so a buyer gains little from paying more.
The cost of changing it was the number of places the old price lived: a demo video description, two dev.to posts, a Substack post and a data marketplace listing all needed editing. On 26 Oct I found the video description still said $0.004 and fixed it.
What I changed: I now keep prices out of short and SEO descriptions entirely. The price lives in the pricing table and the README, so there are fewer places to go stale.
6. Flat on every plan, then tiers anyway
On 23 Oct I decided the LEI and Contracts events would stay flat on every plan. The reasons I wrote down: the revenue effect was near nil, the effect on higher-plan callers was unproven, and there was a known SDK charging problem on a tiered Contracts event. Apify's "Enable Store discounts" suggestion was not taken.
On 28 Oct I changed my mind for LEI, and its tiers took effect that day. Also on 28 Oct, in the Console, I split the Property listing price to $1.25 per 1,000 on the Free plan with proportional tiers, and cut the AU product price from $2.00 to $1.50 per 1,000 on Free. The lesson is small: write the reason down, so that when you reverse a decision you know which reason changed.
What I do now
- Charge only for rows the buyer receives. On the Property Actor the run start is charged once, and only when the first rows reach the dataset, so a blocked or empty run costs nothing. The exception is a monitoring run that read listings: it pays the run start even if nothing changed.
- Give worked examples in every README, so a buyer can check the sum.
- Check the numbers on a real run before believing the docs, mine included.
Data notes for our Actors are at data.yappman.com.
Top comments (0)