Knowing when to write your own Python API to extend a Bubble app, for me that usually comes down to when doing compute heavy actions… Bubble’s greatest value proposition is “display stuff in a browser”… it’s not very good at “compute many things” to display in browser. For example, the cost calculator for one of my plugins is powered by a Python endpoint… could I have done that in Bubble? Probably. Is it way easier in Python - yes! Expand the hidden code below and think about how to do it in native Bubble… I probably could have baked this into an Expression element using javascript but… because I already have a Python API setup, just adding this endpoint was easy enough. Beyond that, if trying to fetch data from other APIs/was a longer running process, like I was here, then that’s even more reason to try to do it in Python.
Cost Calculator Endpoint Code
@app.get("/api/v1/get_search_provider_pricing")
def compute_search_provider_costs(
search_provider: str = "algolia",
average_record_kb: float = 0.6,
number_of_records: int = 50000,
monthly_searches: int = 50000,
regions: int = 1,
is_new_algolia_plan: bool = True,
):
def select_typesense_cluster_base_cost(
number_of_records=50000, average_record_kb=0.6, regions=1
):
region_cluster_pricing = {
1: {0.5: 14.40, 1: 21.60, 2: 36, 4: 64.80, 8: 122.40, 16: 180},
3: {0.5: 64.80, 1: 86.40, 2: 129.60, 4: 216.00, 8: 432.00, 16: 669.60},
5: {0.5: 108, 1: 144, 2: 252, 4: 432.00, 8: 828.00, 16: 1260},
}
cluster_pricing = region_cluster_pricing[regions]
cluster_gb = average_record_kb * number_of_records / 1000000
minimum_cluster_gb = cluster_gb * 2
recommended_minimum_cluster_gb = [
key for key in cluster_pricing.keys() if key > minimum_cluster_gb
][0]
base_monthly_price = cluster_pricing[recommended_minimum_cluster_gb]
return recommended_minimum_cluster_gb, base_monthly_price
if search_provider == "algolia":
if is_new_algolia_plan:
if number_of_records <= 100000:
cost_number_of_records = 0
else:
cost_number_of_records = (number_of_records - 100000) / 1000 * 0.4
if monthly_searches <= 10000:
cost_monthly_searches = 0
else:
cost_monthly_searches = (monthly_searches - 10000) / 1000 * 0.5
cost = cost_monthly_searches + cost_number_of_records
else:
if number_of_records <= 10000:
cost_number_of_records = 0
else:
cost_number_of_records = (number_of_records - 10000) / 1000 * 1.0
if monthly_searches <= 10000:
cost_monthly_searches = 0
else:
cost_monthly_searches = (monthly_searches - 10000) / 1000 * 1.0
cost = cost_monthly_searches + cost_number_of_records
elif search_provider == "typesense":
recommended_minimum_cluster_gb, base_monthly_price = (
select_typesense_cluster_base_cost(
number_of_records=number_of_records,
average_record_kb=average_record_kb,
regions=regions,
)
)
# works out to 720MB per day per node across a month multiplied by regions and 0.09 GB
bandwidth_out_cost_base = 0.720 * 30.44 * regions * 0.09
bandwidth_out_cost_searches = (
monthly_searches * average_record_kb * 100 / 1000000 * 0.09
)
cost = (
base_monthly_price + bandwidth_out_cost_base + bandwidth_out_cost_searches
)
return {"cost": cost}