Local GCP.
Zero cost.
Zero restrictions.

Fast, free, open-source GCP emulator built with Quarkus Native. No GCP project, no billing account, no auth token.

Get Started → ★ View on GitHub
4588
Default port
all services, one port
7
Services live
GCS · Pub/Sub · Firestore · more
186
SDK compat tests
Java · Python · Node.js · Go
MIT
License
fork, embed, extend freely

7 GCP services. All of them free.

No project ID, no service account, no billing account. Every service fully unlocked.

Cloud StorageREST JSON / XML
Pub/SubgRPC
FirestoregRPC
DatastoreREST JSON
Secret ManagergRPC
IAMREST JSON
Managed KafkaREST JSON · Redpanda
Cloud Tasks ⏳REST JSON

⏳ In progress — available in an upcoming release

Fast. Lightweight. Zero overhead.

floci-gcp is built with Quarkus Native, the same stack as the rest of the suite. Starts in 24ms, single Docker image, all 7 services on one port.

24ms
Startup time
Quarkus Native binary
1
Docker image
All services in a single container
4588
Primary port
All REST and gRPC services
~13 MiB
Idle memory
Quarkus Native, minimal footprint

Cloud Storage in seconds.

No GCP account, no service account JSON. Just Docker and gcloud.

docker run

docker run --rm -p 4588:4588 \
  floci/floci-gcp:latest

Set env vars

export CLOUDSDK_API_ENDPOINT_OVERRIDES_STORAGE=\
  http://localhost:4588/
export CLOUDSDK_CORE_PROJECT=floci-local

Upload a file

# Create a bucket
gcloud storage buckets create gs://my-bucket

# Write a file and upload it
echo "No billing alert? Must be floci. ☁️" \
  > hello-floci.txt
gcloud storage cp hello-floci.txt \
  gs://my-bucket/hello-floci.txt

# Download it back and read it
gcloud storage cp \
  gs://my-bucket/hello-floci.txt \
  hello-back.txt
cat hello-back.txt

docker-compose

services:
  floci-gcp:
    image: floci/floci-gcp:latest
    ports:
      - "4588:4588"

Python SDK

# pip install google-cloud-storage
import os
from google.cloud import storage

os.environ["STORAGE_EMULATOR_HOST"] = \
  "http://localhost:4588"

client = storage.Client(project="floci-local")
bucket = client.create_bucket("my-bucket")
blob = bucket.blob("hello-floci.txt")
blob.upload_from_string(
  "No billing alert? Must be floci. ☁️"
)
Cloud Storage on :4588. Buckets · Objects · Multipart · Resumable · Copy

Real code. Local environment.

Point your existing GCP client libraries at localhost:4588. No code changes beyond the endpoint.

Python — google-cloud-storage
# pip install google-cloud-storage
import os
from google.cloud import storage

os.environ["STORAGE_EMULATOR_HOST"] = "http://localhost:4588"
client = storage.Client(project="floci-local")

# create a bucket and upload a file
bucket = client.create_bucket("my-bucket")
blob = bucket.blob("data/hello.txt")
blob.upload_from_string("hello from floci-gcp!")

# list objects in the bucket
for b in client.list_blobs("my-bucket"):
    print(b.name, b.size)

# download and read back
print(blob.download_as_text())
gcloud CLI
# set endpoint override
export CLOUDSDK_API_ENDPOINT_OVERRIDES_STORAGE=\
  http://localhost:4588/
export CLOUDSDK_CORE_PROJECT=floci-local

# create a bucket
gcloud storage buckets create gs://my-bucket

# upload a file
echo "hello from floci-gcp!" > hello.txt
gcloud storage cp hello.txt gs://my-bucket/hello.txt

# list objects
gcloud storage ls gs://my-bucket

# download it back
gcloud storage cp gs://my-bucket/hello.txt -
Python — google-cloud-pubsub
# pip install google-cloud-pubsub
import os
from google.cloud import pubsub_v1

os.environ["PUBSUB_EMULATOR_HOST"] = "localhost:4588"
project = "floci-local"

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()

# create topic and subscription
topic = publisher.topic_path(project, "my-topic")
publisher.create_topic(request={"name": topic})

sub = subscriber.subscription_path(project, "my-sub")
subscriber.create_subscription(
    request={"name": sub, "topic": topic}
)

# publish a message
future = publisher.publish(topic, b"hello from floci-gcp!")
print("Published: " + str(future.result()))

# pull and acknowledge
resp = subscriber.pull(
    request={"subscription": sub, "max_messages": 1}
)
for msg in resp.received_messages:
    print(msg.message.data.decode())
    subscriber.acknowledge(
        request={"subscription": sub,
                 "ack_ids": [msg.ack_id]}
    )
Node.js — @google-cloud/pubsub
// npm install @google-cloud/pubsub
process.env.PUBSUB_EMULATOR_HOST = 'localhost:4588';
const { PubSub } = require('@google-cloud/pubsub');
const pubsub = new PubSub({ projectId: 'floci-local' });

async function run() {
  const [topic] = await pubsub
    .createTopic('my-topic');
  const [sub] = await topic
    .createSubscription('my-sub');

  // publish a message
  const msgId = await topic.publishMessage({
    data: Buffer.from('hello from floci-gcp!'),
  });
  console.log('Published: ' + msgId);

  // receive one message
  sub.on('message', msg => {
    console.log(msg.data.toString());
    msg.ack();
    sub.removeAllListeners();
  });
}
run();
Python — google-cloud-firestore
# pip install google-cloud-firestore
import os
from google.cloud import firestore

os.environ["FIRESTORE_EMULATOR_HOST"] = "localhost:4588"
db = firestore.Client(project="floci-local")

# write a document
ref = db.collection("users").document("alice")
ref.set({"name": "Alice", "score": 42})

# read it back
doc = ref.get()
print(doc.to_dict())

# query with a filter
for doc in (
    db.collection("users")
      .where("score", ">=", 40)
      .stream()
):
    print(doc.id, doc.to_dict())
Node.js — @google-cloud/firestore
// npm install @google-cloud/firestore
process.env.FIRESTORE_EMULATOR_HOST = 'localhost:4588';
const { Firestore } = require('@google-cloud/firestore');
const db = new Firestore({ projectId: 'floci-local' });

async function run() {
  // write a document
  const ref = db.collection('users').doc('alice');
  await ref.set({
    name: 'Alice', score: 42, active: true
  });

  // read it back
  const doc = await ref.get();
  console.log(doc.data());

  // query with a filter
  const snap = await db.collection('users')
    .where('score', '>=', 40).get();
  snap.forEach(d => console.log(d.id, d.data()));
}
run();
Python — google-cloud-secret-manager
# pip install google-cloud-secret-manager
import os
from google.cloud import secretmanager

os.environ["SECRETMANAGER_EMULATOR_HOST"] = \
    "localhost:4588"
client = secretmanager.SecretManagerServiceClient()
parent = "projects/floci-local"

# create a secret
secret = client.create_secret(request={
    "parent": parent,
    "secret_id": "db-password",
    "secret": {"replication": {"automatic": {}}},
})

# store the value
client.add_secret_version(request={
    "parent": secret.name,
    "payload": {"data": b"super-secret-value"},
})

# read the latest version
version = secret.name + "/versions/latest"
resp = client.access_secret_version(request={"name": version})
print(resp.payload.data.decode())
gcloud CLI
# set project
export CLOUDSDK_CORE_PROJECT=floci-local

# create a secret
gcloud secrets create db-password \
  --replication-policy automatic

# store the value
echo -n "super-secret-value" | \
  gcloud secrets versions add db-password \
  --data-file=-

# read the latest version
gcloud secrets versions access latest \
  --secret db-password

GCP emulation, done right

The same design philosophy as floci and floci-az: native speed, zero friction, real compatibility.

floci-gcp
Free, MIT licensed, always
No GCP project or service account
No auth token or API key
Native binary, fast cold start
Single Docker image, single port
Real Cloud Function runtimes
Works offline, CI-friendly
Typical GCP emulator
Mixed licenses, free tier has limits
Often requires a GCP project ID
Service account JSON required
JVM startup, slow in CI
Multiple processes, ports, config
Simulated functions, not real
Internet access required for some ops
🚀

Cloud Tasks is coming next

Seven services are live today. Cloud Tasks is in progress. Star the repo to follow along and open an issue if there's a service your team needs.

Already need a cloud emulator?

floci (AWS) and floci-az (Azure) are stable and production-ready for local development today.

Try floci for AWS → Try floci-az for Azure →